ASR_BASE

Change-Id: Icf3719cc0afe3eeb3edc7fa80a2eb5199ca9dda1
diff --git a/toolchain/Config.in b/toolchain/Config.in
new file mode 100644
index 0000000..71ebbeb
--- /dev/null
+++ b/toolchain/Config.in
@@ -0,0 +1,379 @@
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+menuconfig TARGET_OPTIONS
+	bool "Target Options"  if DEVEL
+
+	config TARGET_OPTIMIZATION
+		string "Target Optimizations" if TARGET_OPTIONS
+		default DEFAULT_TARGET_OPTIMIZATION
+		help
+		  Optimizations to use when building for the target host.
+
+	config SOFT_FLOAT
+		bool "Use software floating point by default" if TARGET_OPTIONS
+		default y if !HAS_FPU
+		depends on arm || armeb || powerpc || mipsel || mips || mips64el || mips64
+		help
+		  If your target CPU does not have a Floating Point Unit (FPU) or a
+		  kernel FPU emulator, but you still wish to support floating point
+		  functions, then everything will need to be compiled with soft floating
+		  point support (-msoft-float).
+
+		  Most people will answer N.
+
+	config USE_MIPS16
+		bool "Build packages with MIPS16 instructions" if TARGET_OPTIONS
+		depends on HAS_MIPS16
+		default y
+		help
+		  If your target CPU does support the MIPS16 instruction set
+		  and you want to use it for packages, enable this option.
+		  MIPS16 produces smaller binaries thus reducing pressure on
+		  caches and TLB.
+
+		  Most people will answer N.
+
+
+	choice BPF_TOOLCHAIN
+		prompt "BPF toolchain" if DEVEL
+		default BPF_TOOLCHAIN_PREBUILT if HAS_PREBUILT_LLVM_TOOLCHAIN
+		default BPF_TOOLCHAIN_BUILD_LLVM
+
+		config BPF_TOOLCHAIN_NONE
+			bool "None"
+
+		config BPF_TOOLCHAIN_PREBUILT
+			bool "Use prebuilt LLVM toolchain"
+			depends on HAS_PREBUILT_LLVM_TOOLCHAIN
+			select USE_LLVM_PREBUILT
+
+		config BPF_TOOLCHAIN_HOST
+			select USE_LLVM_HOST
+			bool "Use host LLVM toolchain"
+
+		config BPF_TOOLCHAIN_BUILD_LLVM
+			select USE_LLVM_BUILD if NEED_BPF_TOOLCHAIN
+			bool "Build LLVM toolchain for eBPF"
+			help
+			  If enabled, a LLVM toolchain for building eBPF binaries will be built.
+			  If this is not enabled, eBPF packages can only be built if the host
+			  has a suitable toolchain
+	endchoice
+
+	config BPF_TOOLCHAIN_HOST_PATH
+		string
+		depends on BPF_TOOLCHAIN_HOST
+		prompt "Host LLVM toolchain path (prefix)" if DEVEL
+		default "/usr/local/opt/llvm" if HOST_OS_MACOS
+		default ""
+
+menuconfig EXTERNAL_TOOLCHAIN
+	bool
+	prompt "Use external toolchain"  if DEVEL
+	help
+	  If enabled, the buildroot will compile using an existing toolchain instead of
+	  compiling one.
+
+	config NATIVE_TOOLCHAIN
+		bool
+		prompt "Use host's toolchain"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN
+		select NO_STRIP
+		help
+		  If enabled, the buildroot will compile using the native toolchain for your
+		  host instead of compiling one.
+
+	config TARGET_NAME
+		string
+		prompt "Target name"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "aarch64-unknown-linux-gnu"  if aarch64
+		default "aarch64_be-unknown-linux-gnu"  if aarch64_be
+		default "arm-unknown-linux-gnu"      if arm
+		default "armeb-unknown-linux-gnu"    if armeb
+		default "i486-unknown-linux-gnu"     if i386
+		default "loongarch64-unknown-linux-gnu" if loongarch64
+		default "mips-unknown-linux-gnu"     if mips
+		default "mipsel-unknown-linux-gnu"   if mipsel
+		default "powerpc-unknown-linux-gnu"  if powerpc
+		default "x86_64-unknown-linux-gnu"   if x86_64
+
+	config TOOLCHAIN_PREFIX
+		string
+		prompt "Toolchain prefix"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "aarch64-unknown-linux-gnu"  if aarch64
+		default "aarch64_be-unknown-linux-gnu"  if aarch64_be
+		default "arm-unknown-linux-gnu-"      if arm
+		default "armeb-unknown-linux-gnu-"    if armeb
+		default "i486-unknown-linux-gnu-"     if i386
+		default "loongarch64-unknown-linux-gnu-" if loongarch64
+		default "mips-unknown-linux-gnu-"     if mips
+		default "mipsel-unknown-linux-gnu-"   if mipsel
+		default "powerpc-unknown-linux-gnu-"  if powerpc
+		default "x86_64-unknown-linux-gnu-"   if x86_64
+
+	config TOOLCHAIN_ROOT
+		string
+		prompt "Toolchain root"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "/opt/cross/aarch64-unknown-linux-gnu"  if aarch64
+		default "/opt/cross/aarch64_be-unknown-linux-gnu"  if aarch64_be
+		default "/opt/cross/arm-unknown-linux-gnu"      if arm
+		default "/opt/cross/armeb-unknown-linux-gnu"    if armeb
+		default "/opt/cross/i486-unknown-linux-gnu"     if i386
+		default "/opt/cross/loongarch64-unknown-linux-gnu" if loongarch64
+		default "/opt/cross/mips-unknown-linux-gnu"     if mips
+		default "/opt/cross/mipsel-unknown-linux-gnu"   if mipsel
+		default "/opt/cross/powerpc-unknown-linux-gnu"  if powerpc
+		default "/opt/cross/x86_64-unknown-linux-gnu"   if x86_64
+
+	choice TOOLCHAIN_LIBC_TYPE
+		prompt "Toolchain libc"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default EXTERNAL_TOOLCHAIN_LIBC_USE_MUSL
+		help
+		  Specify the libc type used by the external toolchain. The given value
+		  is passed as -m flag to all gcc and g++ invocations. This is mainly
+		  intended for multilib toolchains which support glibc and uclibc at
+		  the same time. If no value is specified, no -m flag is passed.
+
+		config EXTERNAL_TOOLCHAIN_LIBC_USE_GLIBC
+			bool "glibc"
+			select USE_GLIBC
+
+		config EXTERNAL_TOOLCHAIN_LIBC_USE_MUSL
+			bool "musl"
+			select USE_MUSL
+
+	endchoice
+
+	config EXTERNAL_GCC_VERSION
+		string
+		prompt "External Toolchain GCC Version" if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		help
+		  Manually specify the GCC version used by the selected
+		  external toolchain.
+
+	config TOOLCHAIN_LIBC
+		string
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "glibc" if EXTERNAL_TOOLCHAIN_LIBC_USE_GLIBC
+		default "musl" if EXTERNAL_TOOLCHAIN_LIBC_USE_MUSL
+
+	config TOOLCHAIN_BIN_PATH
+		string
+		prompt "Toolchain program path"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "./usr/bin ./bin"
+		help
+		  Specify additional directories searched for toolchain binaries
+		  (override PATH). Use ./DIR for directories relative to the root above.
+
+	config TOOLCHAIN_INC_PATH
+		string
+		prompt "Toolchain include path"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "./usr/include ./include/fortify ./include" if EXTERNAL_TOOLCHAIN_LIBC_USE_MUSL
+		default "./usr/include ./include"
+		help
+		  Specify additional directories searched for header files (override
+		  CPPFLAGS). Use ./DIR for directories relative to the root above.
+
+	config TOOLCHAIN_LIB_PATH
+		string
+		prompt "Toolchain library path"  if DEVEL
+		depends on EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+		default "./usr/lib ./lib"
+		help
+		  Specify additional directories searched for libraries (override LDFLAGS).
+		  Use ./DIR for directories relative to the root above.
+
+config NEED_TOOLCHAIN
+	bool
+	depends on DEVEL
+	default y if !EXTERNAL_TOOLCHAIN
+
+menuconfig TOOLCHAINOPTS
+	bool "Toolchain Options"  if DEVEL
+	depends on NEED_TOOLCHAIN
+
+menuconfig EXTRA_TARGET_ARCH
+	bool
+	prompt "Enable an extra toolchain target architecture" if TOOLCHAINOPTS
+	depends on !sparc
+	help
+	  Some builds may require a 'biarch' toolchain. This option
+	  allows you to specify an additional target arch.
+
+	  Most people will answer N here.
+
+	config EXTRA_TARGET_ARCH_NAME
+		string
+		prompt "Extra architecture name" if EXTRA_TARGET_ARCH
+		help
+		  Specify the cpu name (eg powerpc64 or x86_64) of the
+		  additional target architecture.
+
+	config EXTRA_TARGET_ARCH_OPTS
+		string
+		prompt "Extra architecture compiler options" if EXTRA_TARGET_ARCH
+		help
+		  If you're specifying an addition target architecture,
+		  you'll probably need to also provide options to make
+		  the compiler use this alternate arch.
+
+		  For example, if you're building a compiler that can build
+		  both powerpc and powerpc64 binaries, you'll need to
+		  specify -m64 here.
+
+
+	choice
+		prompt "MIPS64 user-land ABI" if TOOLCHAINOPTS && (mips64 || mips64el)
+		default MIPS64_ABI_N64
+		help
+		   MIPS64 supports 3 different user-land ABIs: o32 (legacy),
+		   n32 and n64.
+
+		config MIPS64_ABI_N64
+			bool "n64"
+
+		config MIPS64_ABI_N32
+			depends on !LIBC_USE_MUSL
+			bool "n32"
+
+		config MIPS64_ABI_O32
+			bool "o32"
+
+	endchoice
+
+comment "Binary tools"
+	depends on TOOLCHAINOPTS
+
+source "toolchain/binutils/Config.in"
+
+config DWARVES
+	bool
+	prompt "Build pahole" if TOOLCHAINOPTS
+	depends on !HOST_OS_MACOS
+	help
+	  Enable if you want to build pahole and the dwarves tools.
+
+comment "Compiler"
+	depends on TOOLCHAINOPTS
+
+source "toolchain/gcc/Config.in"
+
+config NASM
+	bool
+	depends on ( i386 || x86_64 )
+	prompt "Build nasm" if TOOLCHAINOPTS
+	default y
+	help
+	  Enable if you want to build nasm
+
+comment "C Library"
+	depends on TOOLCHAINOPTS
+
+choice
+	prompt "C Library implementation" if TOOLCHAINOPTS
+	default LIBC_USE_GLIBC if arc
+	default LIBC_USE_MUSL
+	help
+	  Select the C library implementation.
+
+	config LIBC_USE_GLIBC
+		bool "Use glibc"
+		select USE_GLIBC
+
+	config LIBC_USE_MUSL
+		select USE_MUSL
+		bool "Use musl"
+		depends on !arc
+
+endchoice
+
+source "toolchain/musl/Config.in"
+
+comment "Debuggers"
+	depends on TOOLCHAINOPTS
+
+config GDB
+	bool
+	prompt "Build gdb" if TOOLCHAINOPTS
+	default y if !EXTERNAL_TOOLCHAIN
+	help
+	  Enable if you want to build the gdb.
+
+config GDB_PYTHON
+	bool
+	depends on GDB
+	prompt "Build gdb with python binding"
+	
+	help
+	  Enable the python bindings for GDB to allow using python in the gdb shell.
+
+config HAS_BPF_TOOLCHAIN
+	default y if !BPF_TOOLCHAIN_NONE
+	bool
+
+config NEED_BPF_TOOLCHAIN
+	bool
+
+config HAS_PREBUILT_LLVM_TOOLCHAIN
+	def_bool $(shell, [ -f llvm-bpf/.llvm-version ] && echo y || echo n)
+
+config USE_LLVM_HOST
+	bool
+
+config USE_LLVM_PREBUILT
+	default y if !DEVEL && !BUILDBOT && HAS_PREBUILT_LLVM_TOOLCHAIN
+	bool
+
+config USE_LLVM_BUILD
+	default y if !DEVEL && NEED_BPF_TOOLCHAIN && (BUILDBOT || !HAS_PREBUILT_LLVM_TOOLCHAIN)
+	bool
+
+config USE_GLIBC
+	default y if !TOOLCHAINOPTS && !EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN && (arc)
+	bool
+
+config USE_MUSL
+	default y if !TOOLCHAINOPTS && !EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN && !(arc)
+	bool
+
+config SSP_SUPPORT
+	default y if !PKG_CC_STACKPROTECTOR_NONE
+	bool
+
+config USE_EXTERNAL_LIBC
+	bool
+	default y if EXTERNAL_TOOLCHAIN || NATIVE_TOOLCHAIN
+
+source "toolchain/binutils/Config.version"
+source "toolchain/gcc/Config.version"
+
+config LIBC
+	string
+	default "glibc"   if USE_GLIBC
+	default "musl"	  if USE_MUSL
+
+config TARGET_SUFFIX
+	string
+	default "gnueabi"         if USE_GLIBC && (arm || armeb)
+	default "gnu"             if USE_GLIBC && !(arm || armeb)
+	default "muslgnueabi"     if USE_MUSL && (arm || armeb)
+	default "musl"            if USE_MUSL && !(arm || armeb)
+
+config MIPS64_ABI
+	depends on mips64 || mips64el
+	string
+	default "64" if MIPS64_ABI_N64
+	default "n32" if MIPS64_ABI_N32
+	default "32" if MIPS64_ABI_O32
+	default "64"
diff --git a/toolchain/Makefile b/toolchain/Makefile
new file mode 100644
index 0000000..821f418
--- /dev/null
+++ b/toolchain/Makefile
@@ -0,0 +1,96 @@
+# 
+# Copyright (C) 2007-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+# Main makefile for the toolchain
+#
+# Steps:
+# 1) toolchain/binutils/compile
+#    build & install binutils
+# 2) toolchain/gcc/minimal/compile
+#    build & install a minimal gcc, needed for steps 3 & 4
+# 3) toolchain/kernel-headers/compile
+#    install kernel headers, needed for step 4
+# 4) toolchain/libc/headers/compile
+#    build & install libc headers & support files, needed for step 5
+# 5) toolchain/gcc/initial/compile
+#    build & install an initial gcc, needed for step 6
+# 6) toolchain/libc/compile
+#    build & install the final libc
+# 7) toolchain/gcc/final/compile
+#    build & install the final gcc
+#
+# For musl, steps 2 and 4 are skipped, and step 3 is done after 5
+
+curdir:=toolchain
+
+# subdirectories to descend into
+$(curdir)/builddirs := $(if $(CONFIG_GDB),gdb) $(if $(CONFIG_EXTERNAL_TOOLCHAIN),wrapper,kernel-headers binutils gcc/initial gcc/final $(LIBC) fortify-headers) $(if $(CONFIG_NASM),nasm) $(if $(CONFIG_USE_MOLD),mold)
+
+# builddir dependencies
+ifeq ($(CONFIG_EXTERNAL_TOOLCHAIN),)
+  ifdef CONFIG_USE_MUSL
+    $(curdir)/gcc/initial/compile:=$(curdir)/binutils/compile
+    $(curdir)/kernel-headers/compile:=$(curdir)/gcc/initial/compile
+  else
+    $(curdir)/builddirs += $(LIBC)/headers gcc/minimal
+    $(curdir)/gcc/minimal/compile:=$(curdir)/binutils/compile
+    $(curdir)/kernel-headers/compile:=$(curdir)/gcc/minimal/compile
+    $(curdir)/$(LIBC)/headers/compile:=$(curdir)/kernel-headers/compile
+    $(curdir)/gcc/initial/compile:=$(curdir)/$(LIBC)/headers/compile
+  endif
+
+  $(curdir)/$(LIBC)/compile:=$(curdir)/gcc/initial/compile $(curdir)/kernel-headers/compile
+  $(curdir)/gcc/final/compile:=$(curdir)/$(LIBC)/compile
+endif
+
+ifndef DUMP_TARGET_DB
+ifneq ($(ARCH),)
+  $(TOOLCHAIN_DIR)/info.mk: .config
+	@for dir in $(TOOLCHAIN_DIR); do ( \
+		$(if $(QUIET),,set -x;) \
+		mkdir -p "$$dir"; \
+		cd "$$dir"; \
+		ln -nsf lib lib64; \
+		ln -nsf lib lib32; \
+		mkdir -p stamp lib usr/include usr/lib ; \
+	); done
+	@grep GCC_VERSION $@ >/dev/null 2>&1 || $(INSTALL_DATA) $(TOPDIR)/toolchain/info.mk $@
+	@touch $@
+endif
+endif
+
+ifdef CONFIG_BUILDBOT
+ifneq ($(wildcard $(TOPDIR)/.git),)
+  $(TOOLCHAIN_DIR)/stamp/.ver_check: $(TMP_DIR)/.build
+	cd "$(TOPDIR)"; git log --format=%h -1 toolchain > $(TMP_DIR)/.ver_check
+	cmp -s $(TMP_DIR)/.ver_check $@ || { \
+		rm -rf $(BUILD_DIR) $(STAGING_DIR) $(TOOLCHAIN_DIR) $(BUILD_DIR_TOOLCHAIN); \
+		mkdir -p $(TOOLCHAIN_DIR)/stamp; \
+		mv $(TMP_DIR)/.ver_check $@; \
+	}
+
+$(TOOLCHAIN_DIR)/info.mk $(STAGING_DIR)/.prepared: $(TOOLCHAIN_DIR)/stamp/.ver_check
+endif
+endif
+
+# prerequisites for the individual targets
+$(curdir)/ := .config prereq
+$(curdir)//compile = $(STAGING_DIR)/.prepared $(TOOLCHAIN_DIR)/info.mk $(tools/stamp-compile)
+
+ifndef DUMP_TARGET_DB
+$(TOOLCHAIN_DIR)/stamp/.gcc_final_installed:
+endif
+
+$(curdir)/install: $(curdir)/compile
+
+ifeq ($(TOOLS_REFRESH),1)
+$(eval $(call stampfile,$(curdir),toolchain,compile,$(TOOLCHAIN_DIR)/stamp/.gcc_final_installed,,$(TOOLCHAIN_DIR)))
+$(eval $(call stampfile,$(curdir),toolchain,check,$(TMP_DIR)/.build))
+$(eval $(call subdir,$(curdir)))
+else
+$(curdir)/builddirs=
+$(eval $(foreach target,$(SUBTARGETS),$(call subtarget,$(curdir),$(target))))
+endif
diff --git a/toolchain/binutils/Config.in b/toolchain/binutils/Config.in
new file mode 100644
index 0000000..e2721b1
--- /dev/null
+++ b/toolchain/binutils/Config.in
@@ -0,0 +1,27 @@
+# Choose binutils version.
+
+choice
+	prompt "Binutils Version" if TOOLCHAINOPTS
+	default BINUTILS_USE_VERSION_2_42
+	help
+	  Select the version of binutils you wish to use.
+
+	config BINUTILS_USE_VERSION_2_40
+		bool "Binutils 2.40"
+		select BINUTILS_VERSION_2_40
+
+	config BINUTILS_USE_VERSION_2_42
+		bool "Binutils 2.42"
+		select BINUTILS_VERSION_2_42
+
+	config BINUTILS_USE_VERSION_2_43
+		bool "Binutils 2.43.1"
+		select BINUTILS_VERSION_2_43
+endchoice
+
+config EXTRA_BINUTILS_CONFIG_OPTIONS
+	string
+	prompt "Additional binutils configure options" if TOOLCHAINOPTS
+	default ""
+	help
+	    Any additional binutils options you may want to include....
diff --git a/toolchain/binutils/Config.version b/toolchain/binutils/Config.version
new file mode 100644
index 0000000..f616cdd
--- /dev/null
+++ b/toolchain/binutils/Config.version
@@ -0,0 +1,16 @@
+
+config BINUTILS_VERSION_2_40
+	bool
+
+config BINUTILS_VERSION_2_42
+	default y if !TOOLCHAINOPTS
+	bool
+
+config BINUTILS_VERSION_2_43
+	bool
+
+config BINUTILS_VERSION
+	string
+	default "2.40"			if BINUTILS_VERSION_2_40
+	default "2.42"			if BINUTILS_VERSION_2_42
+	default "2.43.1"		if BINUTILS_VERSION_2_43
diff --git a/toolchain/binutils/Makefile b/toolchain/binutils/Makefile
new file mode 100644
index 0000000..63f0e07
--- /dev/null
+++ b/toolchain/binutils/Makefile
@@ -0,0 +1,103 @@
+#
+# Copyright (C) 2006-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=binutils
+PKG_VERSION:=$(call qstrip,$(CONFIG_BINUTILS_VERSION))
+BIN_VERSION:=$(PKG_VERSION)
+
+PKG_SOURCE_URL:=@GNU/binutils/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_CPE_ID:=cpe:/a:gnu:binutils
+
+TAR_OPTIONS += --exclude='*.rej'
+
+ifeq ($(PKG_VERSION),2.40)
+  PKG_HASH:=0f8a4c272d7f17f369ded10a4aca28b8e304828e95526da482b0ccc4dfc9d8e1
+endif
+
+ifeq ($(PKG_VERSION),2.42)
+  PKG_HASH:=f6e4d41fd5fc778b06b7891457b3620da5ecea1006c6a4a41ae998109f85a800
+endif
+
+ifeq ($(PKG_VERSION),2.43.1)
+  PKG_HASH:=13f74202a3c4c51118b797a39ea4200d3f6cfbe224da6d1d95bb938480132dfd
+endif
+
+HOST_BUILD_PARALLEL:=1
+
+PATCH_DIR:=./patches/$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+ifdef CONFIG_GCC_USE_GRAPHITE
+  GRAPHITE_CONFIGURE:= --with-isl=$(STAGING_DIR_HOST)
+else
+  GRAPHITE_CONFIGURE:= --without-isl --without-cloog
+endif
+
+HOST_CONFIGURE_ARGS = \
+	--prefix=$(TOOLCHAIN_DIR) \
+	--build=$(GNU_HOST_NAME) \
+	--host=$(GNU_HOST_NAME) \
+	--target=$(REAL_GNU_TARGET_NAME) \
+	--with-sysroot=$(TOOLCHAIN_DIR) \
+	--with-system-zlib \
+	--with-zstd \
+	--enable-deterministic-archives \
+	--enable-plugins \
+	--enable-lto \
+	--disable-gprofng \
+	--disable-multilib \
+	--disable-werror \
+	--disable-nls \
+	--disable-sim \
+	--disable-gdb \
+	$(GRAPHITE_CONFIGURE) \
+	$(SOFT_FLOAT_CONFIG_OPTION) \
+	$(call qstrip,$(CONFIG_EXTRA_BINUTILS_CONFIG_OPTIONS))
+
+ifneq ($(CONFIG_SSP_SUPPORT),)
+  HOST_CONFIGURE_ARGS+= \
+		--enable-libssp
+else
+  HOST_CONFIGURE_ARGS+= \
+		--disable-libssp
+endif
+
+ifneq ($(CONFIG_EXTRA_TARGET_ARCH),)
+  HOST_CONFIGURE_ARGS+= \
+		--enable-targets=$(call qstrip,$(CONFIG_EXTRA_TARGET_ARCH_NAME))-linux-$(TARGET_SUFFIX)
+endif
+
+HOST_CONFIGURE_VARS += \
+	acx_cv_cc_gcc_supports_ada=false
+
+define Host/Prepare
+	$(call Host/Prepare/Default)
+	ln -snf $(notdir $(HOST_BUILD_DIR)) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+	$(CP) $(SCRIPT_DIR)/config.{guess,sub} $(HOST_BUILD_DIR)/
+endef
+
+define Host/Compile
+	+$(MAKE) $(HOST_JOBS) -C $(HOST_BUILD_DIR) all
+endef
+
+define Host/Install
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		install
+	$(call FixupLibdir,$(TOOLCHAIN_DIR))
+	$(CP) $(TOOLCHAIN_DIR)/bin/$(REAL_GNU_TARGET_NAME)-readelf $(HOST_BUILD_PREFIX)/bin/readelf
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/binutils/patches/2.40/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch b/toolchain/binutils/patches/2.40/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch
new file mode 100644
index 0000000..9c7635d
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch
@@ -0,0 +1,2172 @@
+From af969b14aedcc0ae27dcefab4327ff2d153dec8b Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Thu, 28 Mar 2024 19:25:42 +1030
+Subject: [PATCH 1/2] PR 30569, always call elf_backend_size_dynamic_sections
+
+This largely mechanical patch is preparation for a followup patch.
+
+For quite some time I've thought that it would be useful to call
+elf_backend_size_dynamic_sections even when no dynamic objects are
+seen by the linker.  That's what this patch does, with some renaming.
+There are no functional changes to the linker, just a move of the
+dynobj test in bfd_elf_size_dynamic_sections to target backend
+functions, replacing the asserts/aborts already there.  No doubt some
+of the current always_size_sections functions could be moved to
+size_dynamic_sections but I haven't made that change.
+
+Because both hooks are now always called, I have renamed
+always_size_sections to early_size_sections and size_dynamic_sections
+to late_size_sections.  I condisdered calling late_size_sections plain
+size_sections, since this is the usual target dynamic section sizing
+hook, but decided that searching the sources for "size_sections" would
+then hit early_size_sections and other functions.
+---
+ bfd/elf-bfd.h          | 35 +++++++++++++++++------------------
+ bfd/elf-m10300.c       | 11 ++++++-----
+ bfd/elf32-arc.c        |  9 +++++----
+ bfd/elf32-arm.c        | 15 ++++++++-------
+ bfd/elf32-bfin.c       | 31 ++++++++++++++++---------------
+ bfd/elf32-cr16.c       | 11 ++++++-----
+ bfd/elf32-cris.c       | 13 +++++++------
+ bfd/elf32-csky.c       |  8 ++++----
+ bfd/elf32-frv.c        | 23 ++++++++++++-----------
+ bfd/elf32-hppa.c       |  8 ++++----
+ bfd/elf32-i386.c       |  7 +++----
+ bfd/elf32-lm32.c       | 15 ++++++++-------
+ bfd/elf32-m32c.c       |  8 ++++----
+ bfd/elf32-m32r.c       | 11 ++++++-----
+ bfd/elf32-m68k.c       | 16 ++++++++--------
+ bfd/elf32-metag.c      |  8 ++++----
+ bfd/elf32-microblaze.c |  9 +++++----
+ bfd/elf32-mips.c       |  6 ++----
+ bfd/elf32-nds32.c      |  9 +++++----
+ bfd/elf32-nios2.c      | 15 ++++++++-------
+ bfd/elf32-or1k.c       |  9 +++++----
+ bfd/elf32-ppc.c        | 11 ++++++-----
+ bfd/elf32-rl78.c       |  8 ++++----
+ bfd/elf32-s390.c       | 10 +++++-----
+ bfd/elf32-score.c      | 35 ++++++++++++++++++-----------------
+ bfd/elf32-score.h      |  4 ++--
+ bfd/elf32-score7.c     | 13 +++++++------
+ bfd/elf32-sh.c         | 15 +++++++--------
+ bfd/elf32-sparc.c      |  3 +--
+ bfd/elf32-tic6x.c      | 14 +++++++-------
+ bfd/elf32-tilegx.c     |  2 +-
+ bfd/elf32-tilepro.c    | 11 +++++------
+ bfd/elf32-vax.c        | 16 +++++++---------
+ bfd/elf32-xstormy16.c  |  8 ++++----
+ bfd/elf32-xtensa.c     | 13 ++++++-------
+ bfd/elf64-alpha.c      | 19 ++++++++++---------
+ bfd/elf64-hppa.c       | 11 ++++-------
+ bfd/elf64-ia64-vms.c   | 13 +++++++------
+ bfd/elf64-mips.c       |  8 ++++----
+ bfd/elf64-ppc.c        | 12 ++++++------
+ bfd/elf64-s390.c       | 10 +++++-----
+ bfd/elf64-sparc.c      |  4 ++--
+ bfd/elf64-tilegx.c     |  2 +-
+ bfd/elf64-x86-64.c     |  7 +++----
+ bfd/elflink.c          |  9 ++++-----
+ bfd/elfn32-mips.c      |  6 ++----
+ bfd/elfnn-aarch64.c    | 21 +++++++++++----------
+ bfd/elfnn-ia64.c       | 11 ++++++-----
+ bfd/elfnn-kvx.c        | 19 +++++++++----------
+ bfd/elfnn-loongarch.c  |  9 +++++----
+ bfd/elfnn-riscv.c      |  7 ++++---
+ bfd/elfxx-mips.c       | 15 ++++++++-------
+ bfd/elfxx-mips.h       |  4 ++--
+ bfd/elfxx-sparc.c      |  7 ++++---
+ bfd/elfxx-sparc.h      |  2 +-
+ bfd/elfxx-target.h     | 12 ++++++------
+ bfd/elfxx-tilegx.c     |  7 ++++---
+ bfd/elfxx-tilegx.h     |  2 +-
+ bfd/elfxx-x86.c        |  8 ++++----
+ bfd/elfxx-x86.h        |  8 ++++----
+ ld/emultempl/vms.em    |  7 +++----
+ 61 files changed, 343 insertions(+), 337 deletions(-)
+
+--- a/bfd/elf-bfd.h
++++ b/bfd/elf-bfd.h
+@@ -1173,7 +1173,7 @@ struct elf_backend_data
+   /* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend
+      linker for every symbol which is defined by a dynamic object and
+      referenced by a regular object.  This is called after all the
+-     input files have been seen, but before the SIZE_DYNAMIC_SECTIONS
++     input files have been seen, but before the LATE_SIZE_SECTIONS
+      function has been called.  The hash table entry should be
+      bfd_link_hash_defined ore bfd_link_hash_defweak, and it should be
+      defined in a section from a dynamic object.  Dynamic object
+@@ -1185,24 +1185,23 @@ struct elf_backend_data
+   bool (*elf_backend_adjust_dynamic_symbol)
+     (struct bfd_link_info *info, struct elf_link_hash_entry *h);
+ 
+-  /* The ALWAYS_SIZE_SECTIONS function is called by the backend linker
+-     after all the linker input files have been seen but before the
+-     section sizes have been set.  This is called after
+-     ADJUST_DYNAMIC_SYMBOL, but before SIZE_DYNAMIC_SECTIONS.  */
+-  bool (*elf_backend_always_size_sections)
++  /* The EARLY_SIZE_SECTIONS and LATE_SIZE_SECTIONS functions are
++     called by the backend linker after all linker input files have
++     been seen and sections have been assigned to output sections, but
++     before the section sizes have been set.  Both of these functions
++     are called even when no dynamic object is seen by the linker.
++     Between them, they must set the sizes of the dynamic sections and
++     other backend specific sections, and may fill in their contents.
++     Most backends need only use LATE_SIZE_SECTIONS.
++     EARLY_SIZE_SECTIONS is called before --export-dynamic makes some
++     symbols dynamic and before ADJUST_DYNAMIC_SYMBOL processes
++     dynamic symbols, LATE_SIZE_SECTIONS afterwards.  The generic ELF
++     linker can handle the .dynsym, .dynstr and .hash sections.
++     Besides those, these functions must handle the .interp section
++     and any other sections created by CREATE_DYNAMIC_SECTIONS.  */
++  bool (*elf_backend_early_size_sections)
+     (bfd *output_bfd, struct bfd_link_info *info);
+-
+-  /* The SIZE_DYNAMIC_SECTIONS function is called by the ELF backend
+-     linker after all the linker input files have been seen but before
+-     the sections sizes have been set.  This is called after
+-     ADJUST_DYNAMIC_SYMBOL has been called on all appropriate symbols.
+-     It is only called when linking against a dynamic object.  It must
+-     set the sizes of the dynamic sections, and may fill in their
+-     contents as well.  The generic ELF linker can handle the .dynsym,
+-     .dynstr and .hash sections.  This function must handle the
+-     .interp section and any sections created by the
+-     CREATE_DYNAMIC_SECTIONS entry point.  */
+-  bool (*elf_backend_size_dynamic_sections)
++  bool (*elf_backend_late_size_sections)
+     (bfd *output_bfd, struct bfd_link_info *info);
+ 
+   /* The STRIP_ZERO_SIZED_DYNAMIC_SECTIONS function is called by the
+--- a/bfd/elf-m10300.c
++++ b/bfd/elf-m10300.c
+@@ -5012,8 +5012,8 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-_bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
+-					struct bfd_link_info * info)
++_bfd_mn10300_elf_late_size_sections (bfd * output_bfd,
++				     struct bfd_link_info * info)
+ {
+   struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
+   bfd * dynobj;
+@@ -5021,7 +5021,8 @@ _bfd_mn10300_elf_size_dynamic_sections (
+   bool relocs;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5508,8 +5509,8 @@ mn10300_elf_mkobject (bfd *abfd)
+   _bfd_mn10300_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol \
+   _bfd_mn10300_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_mn10300_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_mn10300_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_symbol \
+   _bfd_mn10300_elf_finish_dynamic_symbol
+--- a/bfd/elf32-arc.c
++++ b/bfd/elf32-arc.c
+@@ -2702,8 +2702,8 @@ elf_arc_finish_dynamic_sections (bfd * o
+ 
+ /* Set the sizes of the dynamic sections.  */
+ static bool
+-elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++elf_arc_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			    struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -2711,7 +2711,8 @@ elf_arc_size_dynamic_sections (bfd *outp
+   struct elf_link_hash_table *htab = elf_hash_table (info);
+ 
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -3126,7 +3127,7 @@ arc_elf_relax_section (bfd *abfd, asecti
+ #define elf_backend_finish_dynamic_symbol    elf_arc_finish_dynamic_symbol
+ 
+ #define elf_backend_finish_dynamic_sections  elf_arc_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections    elf_arc_size_dynamic_sections
++#define elf_backend_late_size_sections       elf_arc_late_size_sections
+ 
+ #define elf_backend_can_gc_sections	1
+ #define elf_backend_want_got_plt	1
+--- a/bfd/elf32-arm.c
++++ b/bfd/elf32-arm.c
+@@ -16734,8 +16734,8 @@ bfd_elf32_arm_set_byteswap_code (struct
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info * info)
++elf32_arm_late_size_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info * info)
+ {
+   bfd * dynobj;
+   asection * s;
+@@ -16748,7 +16748,9 @@ elf32_arm_size_dynamic_sections (bfd * o
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
++
+   check_use_blx (htab);
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+@@ -17120,8 +17122,7 @@ elf32_arm_size_dynamic_sections (bfd * o
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bool
+-elf32_arm_always_size_sections (bfd *output_bfd,
+-				struct bfd_link_info *info)
++elf32_arm_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+   struct elf32_arm_link_hash_table *htab;
+@@ -20320,8 +20321,8 @@ elf32_arm_backend_symbol_processing (bfd
+ #define elf_backend_create_dynamic_sections	elf32_arm_create_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	elf32_arm_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	elf32_arm_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	elf32_arm_size_dynamic_sections
+-#define elf_backend_always_size_sections	elf32_arm_always_size_sections
++#define elf_backend_late_size_sections		elf32_arm_late_size_sections
++#define elf_backend_early_size_sections		elf32_arm_early_size_sections
+ #define elf_backend_init_index_section		_bfd_elf_init_2_index_sections
+ #define elf_backend_init_file_header		elf32_arm_init_file_header
+ #define elf_backend_reloc_type_class		elf32_arm_reloc_type_class
+--- a/bfd/elf32-bfin.c
++++ b/bfd/elf32-bfin.c
+@@ -4027,8 +4027,8 @@ _bfinfdpic_size_got_plt (bfd *output_bfd
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++elf32_bfinfdpic_late_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -4037,7 +4037,8 @@ elf32_bfinfdpic_size_dynamic_sections (b
+ 
+   htab = elf_hash_table (info);
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -4086,7 +4087,7 @@ elf32_bfinfdpic_size_dynamic_sections (b
+ }
+ 
+ static bool
+-elf32_bfinfdpic_always_size_sections (bfd *output_bfd,
++elf32_bfinfdpic_early_size_sections (bfd *output_bfd,
+ 				     struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info)
+@@ -5124,15 +5125,16 @@ bfin_discard_copies (struct elf_link_has
+ }
+ 
+ static bool
+-bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
+-			    struct bfd_link_info *info)
++bfin_late_size_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
++			 struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5424,8 +5426,7 @@ struct bfd_elf_special_section const elf
+ #define elf_backend_check_relocs	bfin_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 					bfin_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-					bfin_size_dynamic_sections
++#define elf_backend_late_size_sections	bfin_late_size_sections
+ #define elf_backend_relocate_section	bfin_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+ 					bfin_finish_dynamic_symbol
+@@ -5471,9 +5472,9 @@ struct bfd_elf_special_section const elf
+ #undef bfd_elf32_bfd_link_hash_table_create
+ #define bfd_elf32_bfd_link_hash_table_create \
+ 		bfinfdpic_elf_link_hash_table_create
+-#undef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections \
+-		elf32_bfinfdpic_always_size_sections
++#undef elf_backend_early_size_sections
++#define elf_backend_early_size_sections \
++		elf32_bfinfdpic_early_size_sections
+ 
+ #undef elf_backend_create_dynamic_sections
+ #define elf_backend_create_dynamic_sections \
+@@ -5481,9 +5482,9 @@ struct bfd_elf_special_section const elf
+ #undef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol \
+ 		elf32_bfinfdpic_adjust_dynamic_symbol
+-#undef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections \
+-		elf32_bfinfdpic_size_dynamic_sections
++#undef elf_backend_late_size_sections
++#define elf_backend_late_size_sections \
++		elf32_bfinfdpic_late_size_sections
+ #undef elf_backend_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol \
+ 		elf32_bfinfdpic_finish_dynamic_symbol
+--- a/bfd/elf32-cr16.c
++++ b/bfd/elf32-cr16.c
+@@ -2390,15 +2390,16 @@ _bfd_cr16_elf_adjust_dynamic_symbol (str
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-_bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
+-				     struct bfd_link_info * info)
++_bfd_cr16_elf_late_size_sections (bfd * output_bfd,
++				  struct bfd_link_info * info)
+ {
+   bfd * dynobj;
+   asection * s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -2835,8 +2836,8 @@ _bfd_cr16_elf_reloc_type_class (const st
+ 				  _bfd_cr16_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol \
+ 				  _bfd_cr16_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-				  _bfd_cr16_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++				  _bfd_cr16_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_symbol \
+ 				   _bfd_cr16_elf_finish_dynamic_symbol
+--- a/bfd/elf32-cris.c
++++ b/bfd/elf32-cris.c
+@@ -2527,7 +2527,7 @@ cris_elf_plt_sym_val (bfd_vma i ATTRIBUT
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_cris_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_cris_size_dynamic_sections if no dynamic sections will be
++   or elf_cris_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static bool
+@@ -3508,8 +3508,8 @@ cris_elf_check_relocs (bfd *abfd,
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_cris_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_cris_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_cris_link_hash_table * htab;
+   bfd *dynobj;
+@@ -3521,7 +3521,8 @@ elf_cris_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -4090,8 +4091,8 @@ elf_cris_got_elt_size (bfd *abfd ATTRIBU
+ 	elf_cris_adjust_dynamic_symbol
+ #define elf_backend_copy_indirect_symbol \
+ 	elf_cris_copy_indirect_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elf_cris_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elf_cris_late_size_sections
+ #define elf_backend_init_index_section		_bfd_elf_init_1_index_section
+ #define elf_backend_finish_dynamic_symbol \
+ 	elf_cris_finish_dynamic_symbol
+--- a/bfd/elf32-csky.c
++++ b/bfd/elf32-csky.c
+@@ -1893,8 +1893,8 @@ csky_allocate_dynrelocs (struct elf_link
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-csky_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++csky_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct csky_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1907,7 +1907,7 @@ csky_elf_size_dynamic_sections (bfd *out
+     return false;
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    return false;
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -5344,7 +5344,7 @@ elf32_csky_obj_attrs_handle_unknown (bfd
+ /* Dynamic relocate related API.  */
+ #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol     csky_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections     csky_elf_size_dynamic_sections
++#define elf_backend_late_size_sections        csky_elf_late_size_sections
+ #define elf_backend_finish_dynamic_symbol     csky_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections   csky_elf_finish_dynamic_sections
+ #define elf_backend_rela_normal               1
+--- a/bfd/elf32-frv.c
++++ b/bfd/elf32-frv.c
+@@ -5423,15 +5423,16 @@ _frvfdpic_size_got_plt (bfd *output_bfd,
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++elf32_frvfdpic_late_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   struct _frvfdpic_dynamic_got_plt_info gpinfo;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5472,8 +5473,8 @@ elf32_frvfdpic_size_dynamic_sections (bf
+ }
+ 
+ static bool
+-elf32_frvfdpic_always_size_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++elf32_frvfdpic_early_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info)
+       && !bfd_elf_stack_segment_size (output_bfd, info,
+@@ -6817,9 +6818,9 @@ elf32_frv_grok_psinfo (bfd *abfd, Elf_In
+ #undef bfd_elf32_bfd_link_hash_table_create
+ #define bfd_elf32_bfd_link_hash_table_create \
+ 		frvfdpic_elf_link_hash_table_create
+-#undef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections \
+-		elf32_frvfdpic_always_size_sections
++#undef elf_backend_early_size_sections
++#define elf_backend_early_size_sections \
++		elf32_frvfdpic_early_size_sections
+ 
+ #undef elf_backend_create_dynamic_sections
+ #define elf_backend_create_dynamic_sections \
+@@ -6827,9 +6828,9 @@ elf32_frv_grok_psinfo (bfd *abfd, Elf_In
+ #undef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol \
+ 		elf32_frvfdpic_adjust_dynamic_symbol
+-#undef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections \
+-		elf32_frvfdpic_size_dynamic_sections
++#undef elf_backend_late_size_sections
++#define elf_backend_late_size_sections \
++		elf32_frvfdpic_late_size_sections
+ #undef bfd_elf32_bfd_relax_section
+ #define bfd_elf32_bfd_relax_section \
+   elf32_frvfdpic_relax_section
+--- a/bfd/elf32-hppa.c
++++ b/bfd/elf32-hppa.c
+@@ -2042,8 +2042,8 @@ clobber_millicode_symbols (struct elf_li
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf32_hppa_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf32_hppa_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2057,7 +2057,7 @@ elf32_hppa_size_dynamic_sections (bfd *o
+ 
+   dynobj = htab->etab.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->etab.dynamic_sections_created)
+     {
+@@ -4450,7 +4450,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Inte
+ #define elf_backend_hide_symbol		     elf32_hppa_hide_symbol
+ #define elf_backend_finish_dynamic_symbol    elf32_hppa_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  elf32_hppa_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections    elf32_hppa_size_dynamic_sections
++#define elf_backend_late_size_sections	     elf32_hppa_late_size_sections
+ #define elf_backend_init_index_section	     _bfd_elf_init_1_index_section
+ #define elf_backend_gc_mark_hook	     elf32_hppa_gc_mark_hook
+ #define elf_backend_grok_prstatus	     elf32_hppa_grok_prstatus
+--- a/bfd/elf32-i386.c
++++ b/bfd/elf32-i386.c
+@@ -1933,8 +1933,7 @@ elf_i386_scan_relocs (bfd *abfd,
+ }
+ 
+ static bool
+-elf_i386_always_size_sections (bfd *output_bfd,
+-			       struct bfd_link_info *info)
++elf_i386_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *abfd;
+ 
+@@ -1947,7 +1946,7 @@ elf_i386_always_size_sections (bfd *outp
+ 					     elf_i386_scan_relocs))
+       return false;
+ 
+-  return _bfd_x86_elf_always_size_sections (output_bfd, info);
++  return _bfd_x86_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ /* Set the correct type for an x86 ELF section.  We do this by the
+@@ -4444,7 +4443,7 @@ elf_i386_link_setup_gnu_properties (stru
+ #define bfd_elf32_get_synthetic_symtab	      elf_i386_get_synthetic_symtab
+ 
+ #define elf_backend_relocs_compatible	      _bfd_elf_relocs_compatible
+-#define elf_backend_always_size_sections      elf_i386_always_size_sections
++#define elf_backend_early_size_sections	      elf_i386_early_size_sections
+ #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
+ #define elf_backend_fake_sections	      elf_i386_fake_sections
+ #define elf_backend_finish_dynamic_sections   elf_i386_finish_dynamic_sections
+--- a/bfd/elf32-lm32.c
++++ b/bfd/elf32-lm32.c
+@@ -1906,8 +1906,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-lm32_elf_size_dynamic_sections (bfd *output_bfd,
+-				struct bfd_link_info *info)
++lm32_elf_late_size_sections (bfd *output_bfd,
++			     struct bfd_link_info *info)
+ {
+   struct elf_lm32_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1920,7 +1920,8 @@ lm32_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -2309,7 +2310,7 @@ lm32_elf_create_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-lm32_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++lm32_elf_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info))
+     {
+@@ -2395,7 +2396,7 @@ lm32_elf_fdpic_copy_private_bfd_data (bf
+ #define bfd_elf32_bfd_link_hash_table_create	lm32_elf_link_hash_table_create
+ #define elf_backend_check_relocs		lm32_elf_check_relocs
+ #define elf_backend_reloc_type_class		lm32_elf_reloc_type_class
+-#define elf_backend_size_dynamic_sections	lm32_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		lm32_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym		_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_create_dynamic_sections	lm32_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	lm32_elf_finish_dynamic_sections
+@@ -2416,8 +2417,8 @@ lm32_elf_fdpic_copy_private_bfd_data (bf
+ #undef	elf32_bed
+ #define	elf32_bed		elf32_lm32fdpic_bed
+ 
+-#undef	elf_backend_always_size_sections
+-#define elf_backend_always_size_sections	lm32_elf_always_size_sections
++#undef	elf_backend_early_size_sections
++#define elf_backend_early_size_sections		lm32_elf_early_size_sections
+ #undef	bfd_elf32_bfd_copy_private_bfd_data
+ #define bfd_elf32_bfd_copy_private_bfd_data	lm32_elf_fdpic_copy_private_bfd_data
+ 
+--- a/bfd/elf32-m32c.c
++++ b/bfd/elf32-m32c.c
+@@ -773,8 +773,8 @@ m32c_elf_finish_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-m32c_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++m32c_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -2131,8 +2131,8 @@ _bfd_m32c_elf_eh_frame_address_size (bfd
+ #define elf_backend_check_relocs		m32c_elf_check_relocs
+ #define elf_backend_object_p			m32c_elf_object_p
+ #define elf_symbol_leading_char			('_')
+-#define elf_backend_always_size_sections \
+-  m32c_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  m32c_elf_early_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   m32c_elf_finish_dynamic_sections
+ 
+--- a/bfd/elf32-m32r.c
++++ b/bfd/elf32-m32r.c
+@@ -1958,8 +1958,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-m32r_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++m32r_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1968,7 +1968,7 @@ m32r_elf_size_dynamic_sections (bfd *out
+   bfd *ibfd;
+ 
+ #ifdef DEBUG_PIC
+-  printf ("m32r_elf_size_dynamic_sections()\n");
++  printf ("m32r_elf_late_size_sections()\n");
+ #endif
+ 
+   htab = m32r_elf_hash_table (info);
+@@ -1976,7 +1976,8 @@ m32r_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -3658,7 +3659,7 @@ m32r_elf_reloc_type_class (const struct
+ 
+ #define elf_backend_create_dynamic_sections	m32r_elf_create_dynamic_sections
+ #define bfd_elf32_bfd_link_hash_table_create	m32r_elf_link_hash_table_create
+-#define elf_backend_size_dynamic_sections	m32r_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		m32r_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym		_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_sections	m32r_elf_finish_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol	m32r_elf_adjust_dynamic_symbol
+--- a/bfd/elf32-m68k.c
++++ b/bfd/elf32-m68k.c
+@@ -2934,7 +2934,7 @@ elf_m68k_get_plt_info (bfd *output_bfd)
+    It's a convenient place to determine the PLT style.  */
+ 
+ static bool
+-elf_m68k_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf_m68k_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   /* Bind input BFDs to GOTs and calculate sizes of .got and .rela.got
+      sections.  */
+@@ -3107,15 +3107,16 @@ elf_m68k_adjust_dynamic_symbol (struct b
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_m68k_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_m68k_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -4628,12 +4629,11 @@ elf_m68k_grok_psinfo (bfd *abfd, Elf_Int
+ #define bfd_elf32_bfd_final_link	bfd_elf_final_link
+ 
+ #define elf_backend_check_relocs	elf_m68k_check_relocs
+-#define elf_backend_always_size_sections \
+-					elf_m68k_always_size_sections
++#define elf_backend_early_size_sections \
++					elf_m68k_early_size_sections
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf_m68k_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-					elf_m68k_size_dynamic_sections
++#define elf_backend_late_size_sections	elf_m68k_late_size_sections
+ #define elf_backend_final_write_processing	elf_m68k_final_write_processing
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	elf_m68k_relocate_section
+--- a/bfd/elf32-metag.c
++++ b/bfd/elf32-metag.c
+@@ -2717,8 +2717,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_metag_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info *info)
++elf_metag_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   struct elf_metag_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2729,7 +2729,7 @@ elf_metag_size_dynamic_sections (bfd *ou
+   htab = metag_link_hash_table (info);
+   dynobj = htab->etab.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->etab.dynamic_sections_created)
+     {
+@@ -4019,7 +4019,7 @@ elf_metag_plt_sym_val (bfd_vma i, const
+ #define elf_backend_adjust_dynamic_symbol	elf_metag_adjust_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol	elf_metag_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	elf_metag_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	elf_metag_size_dynamic_sections
++#define elf_backend_late_size_sections		elf_metag_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_init_file_header		elf_metag_init_file_header
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -2946,8 +2946,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				      struct bfd_link_info *info)
++microblaze_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				   struct bfd_link_info *info)
+ {
+   struct elf32_mb_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2959,7 +2959,8 @@ microblaze_elf_size_dynamic_sections (bf
+     return false;
+ 
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   /* Set up .got offsets for local syms, and space for local dynamic
+      relocs.  */
+@@ -3477,7 +3478,7 @@ microblaze_elf_add_symbol_hook (bfd *abf
+ #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	microblaze_elf_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	microblaze_elf_finish_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	microblaze_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		microblaze_elf_late_size_sections
+ #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook
+ 
+ #include "elf32-target.h"
+--- a/bfd/elf32-mips.c
++++ b/bfd/elf32-mips.c
+@@ -2534,10 +2534,8 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf32-nds32.c
++++ b/bfd/elf32-nds32.c
+@@ -4302,8 +4302,8 @@ elf32_nds32_add_dynreloc (bfd *output_bf
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info *info)
++nds32_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   struct elf_nds32_link_hash_table *htab;
+   bfd *dynobj;
+@@ -4316,7 +4316,8 @@ nds32_elf_size_dynamic_sections (bfd *ou
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -13984,7 +13985,7 @@ nds32_elf_unify_tls_model (bfd *inbfd, a
+ #define elf_backend_create_dynamic_sections	nds32_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	nds32_elf_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	nds32_elf_finish_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	nds32_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		nds32_elf_late_size_sections
+ #define elf_backend_relocate_section		nds32_elf_relocate_section
+ #define elf_backend_gc_mark_hook		nds32_elf_gc_mark_hook
+ #define elf_backend_grok_prstatus		nds32_elf_grok_prstatus
+--- a/bfd/elf32-nios2.c
++++ b/bfd/elf32-nios2.c
+@@ -5411,7 +5411,7 @@ nios2_elf32_adjust_dynamic_symbol (struc
+   return true;
+ }
+ 
+-/* Worker function for nios2_elf32_size_dynamic_sections.  */
++/* Worker function for nios2_elf32_late_size_sections.  */
+ static bool
+ adjust_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+ {
+@@ -5438,7 +5438,7 @@ adjust_dynrelocs (struct elf_link_hash_e
+   return true;
+ }
+ 
+-/* Another worker function for nios2_elf32_size_dynamic_sections.
++/* Another worker function for nios2_elf32_late_size_sections.
+    Allocate space in .plt, .got and associated reloc sections for
+    dynamic relocs.  */
+ static bool
+@@ -5673,11 +5673,11 @@ allocate_dynrelocs (struct elf_link_hash
+   return true;
+ }
+ 
+-/* Implement elf_backend_size_dynamic_sections:
++/* Implement elf_backend_late_size_sections:
+    Set the sizes of the dynamic sections.  */
+ static bool
+-nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				   struct bfd_link_info *info)
++nios2_elf32_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -5687,7 +5687,8 @@ nios2_elf32_size_dynamic_sections (bfd *
+ 
+   htab = elf32_nios2_hash_table (info);
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   htab->res_n_size = 0;
+   if (htab->root.dynamic_sections_created)
+@@ -6058,7 +6059,7 @@ const struct bfd_elf_special_section elf
+ 					  nios2_elf32_finish_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol nios2_elf32_adjust_dynamic_symbol
+ #define elf_backend_reloc_type_class	  nios2_elf32_reloc_type_class
+-#define elf_backend_size_dynamic_sections nios2_elf32_size_dynamic_sections
++#define elf_backend_late_size_sections	  nios2_elf32_late_size_sections
+ #define elf_backend_add_symbol_hook	  nios2_elf_add_symbol_hook
+ #define elf_backend_copy_indirect_symbol  nios2_elf32_copy_indirect_symbol
+ #define elf_backend_object_p		  nios2_elf32_object_p
+--- a/bfd/elf32-or1k.c
++++ b/bfd/elf32-or1k.c
+@@ -3039,8 +3039,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++or1k_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_or1k_link_hash_table *htab;
+   bfd *dynobj;
+@@ -3053,7 +3053,8 @@ or1k_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -3406,7 +3407,7 @@ or1k_grok_psinfo (bfd *abfd, Elf_Interna
+ #define elf_backend_copy_indirect_symbol	or1k_elf_copy_indirect_symbol
+ #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	or1k_elf_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	or1k_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		or1k_elf_late_size_sections
+ #define elf_backend_adjust_dynamic_symbol	or1k_elf_adjust_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol	or1k_elf_finish_dynamic_symbol
+ 
+--- a/bfd/elf32-ppc.c
++++ b/bfd/elf32-ppc.c
+@@ -5478,8 +5478,8 @@ static const unsigned char glink_eh_fram
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-ppc_elf_size_dynamic_sections (bfd *output_bfd,
+-			       struct bfd_link_info *info)
++ppc_elf_late_size_sections (bfd *output_bfd,
++			    struct bfd_link_info *info)
+ {
+   struct ppc_elf_link_hash_table *htab;
+   asection *s;
+@@ -5487,11 +5487,12 @@ ppc_elf_size_dynamic_sections (bfd *outp
+   bfd *ibfd;
+ 
+ #ifdef DEBUG
+-  fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
++  fprintf (stderr, "ppc_elf_late_size_sections called\n");
+ #endif
+ 
+   htab = ppc_elf_hash_table (info);
+-  BFD_ASSERT (htab->elf.dynobj != NULL);
++  if (htab->elf.dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -10414,7 +10415,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou
+ #define elf_backend_copy_indirect_symbol	ppc_elf_copy_indirect_symbol
+ #define elf_backend_adjust_dynamic_symbol	ppc_elf_adjust_dynamic_symbol
+ #define elf_backend_add_symbol_hook		ppc_elf_add_symbol_hook
+-#define elf_backend_size_dynamic_sections	ppc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		ppc_elf_late_size_sections
+ #define elf_backend_hash_symbol			ppc_elf_hash_symbol
+ #define elf_backend_finish_dynamic_symbol	ppc_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	ppc_elf_finish_dynamic_sections
+--- a/bfd/elf32-rl78.c
++++ b/bfd/elf32-rl78.c
+@@ -1440,8 +1440,8 @@ rl78_elf_finish_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-rl78_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++rl78_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -2609,8 +2609,8 @@ rl78_elf_relax_section (bfd *abfd,
+ 
+ #define bfd_elf32_bfd_relax_section		rl78_elf_relax_section
+ #define elf_backend_check_relocs		rl78_elf_check_relocs
+-#define elf_backend_always_size_sections \
+-  rl78_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  rl78_elf_early_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   rl78_elf_finish_dynamic_sections
+ 
+--- a/bfd/elf32-s390.c
++++ b/bfd/elf32-s390.c
+@@ -1366,7 +1366,7 @@ elf_s390_gc_mark_hook (asection *sec,
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_s390_size_dynamic_sections if no dynamic sections will be
++   or elf_s390_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static void
+@@ -1778,8 +1778,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_s390_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1790,7 +1790,7 @@ elf_s390_size_dynamic_sections (bfd *out
+   htab = elf_s390_hash_table (info);
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3926,7 +3926,7 @@ elf32_s390_merge_private_bfd_data (bfd *
+ #define elf_backend_gc_mark_hook	      elf_s390_gc_mark_hook
+ #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
+ #define elf_backend_relocate_section	      elf_s390_relocate_section
+-#define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
++#define elf_backend_late_size_sections	      elf_s390_late_size_sections
+ #define elf_backend_init_index_section	      _bfd_elf_init_1_index_section
+ #define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
+ #define elf_backend_grok_psinfo		      elf_s390_grok_psinfo
+--- a/bfd/elf32-score.c
++++ b/bfd/elf32-score.c
+@@ -1089,7 +1089,7 @@ score_elf_got_info (bfd *abfd, asection
+    appear towards the end.  This reduces the amount of GOT space
+    required.  MAX_LOCAL is used to set the number of local symbols
+    known to be in the dynamic symbol table.  During
+-   s3_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
++   s3_bfd_score_elf_late_size_sections, this value is 1.  Afterward, the
+    section symbols are added and the count is higher.  */
+ static bool
+ score_elf_sort_hash_table (struct bfd_link_info *info,
+@@ -3160,8 +3160,8 @@ s3_bfd_score_elf_adjust_dynamic_symbol (
+ /* This function is called after all the input files have been read,
+    and the input sections have been assigned to output sections.  */
+ static bool
+-s3_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				       struct bfd_link_info *info)
++s3_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -3237,14 +3237,15 @@ s3_bfd_score_elf_always_size_sections (b
+ 
+ /* Set the sizes of the dynamic sections.  */
+ static bool
+-s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++s3_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool reltext;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3313,7 +3314,7 @@ s3_bfd_score_elf_size_dynamic_sections (
+ 	}
+       else if (startswith (name, ".got"))
+ 	{
+-	  /* s3_bfd_score_elf_always_size_sections() has already done
++	  /* s3_bfd_score_elf_early_size_sections() has already done
+ 	     most of the work, but some symbols may have been mapped
+ 	     to versions that we must now resolve in the got_entries
+ 	     hash tables.  */
+@@ -4177,22 +4178,22 @@ _bfd_score_elf_adjust_dynamic_symbol (st
+ }
+ 
+ static bool
+-_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+-    return s3_bfd_score_elf_always_size_sections (output_bfd, info);
++    return s3_bfd_score_elf_early_size_sections (output_bfd, info);
+   else
+-    return s7_bfd_score_elf_always_size_sections (output_bfd, info);
++    return s7_bfd_score_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ static bool
+-_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+-    return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info);
++    return s3_bfd_score_elf_late_size_sections (output_bfd, info);
+   else
+-    return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info);
++    return s7_bfd_score_elf_late_size_sections (output_bfd, info);
+ }
+ 
+ static bool
+@@ -4455,10 +4456,10 @@ _bfd_score_elf_common_definition (Elf_In
+   _bfd_score_elf_section_from_bfd_section
+ #define elf_backend_adjust_dynamic_symbol \
+   _bfd_score_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-  _bfd_score_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_score_elf_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  _bfd_score_elf_early_size_sections
++#define elf_backend_late_size_sections \
++  _bfd_score_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_create_dynamic_sections \
+   _bfd_score_elf_create_dynamic_sections
+--- a/bfd/elf32-score.h
++++ b/bfd/elf32-score.h
+@@ -78,10 +78,10 @@ s7_bfd_score_elf_adjust_dynamic_symbol (
+ 					struct elf_link_hash_entry *);
+ 
+ extern bool
+-s7_bfd_score_elf_always_size_sections (bfd *, struct bfd_link_info *);
++s7_bfd_score_elf_early_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern bool
+-s7_bfd_score_elf_size_dynamic_sections (bfd *, struct bfd_link_info *);
++s7_bfd_score_elf_late_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern bool
+ s7_bfd_score_elf_create_dynamic_sections (bfd *, struct bfd_link_info *);
+--- a/bfd/elf32-score7.c
++++ b/bfd/elf32-score7.c
+@@ -975,7 +975,7 @@ score_elf_got_info (bfd *abfd, asection
+    appear towards the end.  This reduces the amount of GOT space
+    required.  MAX_LOCAL is used to set the number of local symbols
+    known to be in the dynamic symbol table.  During
+-   s7_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
++   s7_bfd_score_elf_late_size_sections, this value is 1.  Afterward, the
+    section symbols are added and the count is higher.  */
+ 
+ static bool
+@@ -2969,8 +2969,8 @@ s7_bfd_score_elf_adjust_dynamic_symbol (
+    and the input sections have been assigned to output sections.  */
+ 
+ bool
+-s7_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				       struct bfd_link_info *info)
++s7_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -3047,14 +3047,15 @@ s7_bfd_score_elf_always_size_sections (b
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-s7_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++s7_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool reltext;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3123,7 +3124,7 @@ s7_bfd_score_elf_size_dynamic_sections (
+ 	}
+       else if (startswith (name, ".got"))
+ 	{
+-	  /* s7_bfd_score_elf_always_size_sections() has already done
++	  /* s7_bfd_score_elf_early_size_sections() has already done
+ 	     most of the work, but some symbols may have been mapped
+ 	     to versions that we must now resolve in the got_entries
+ 	     hash tables.  */
+--- a/bfd/elf32-sh.c
++++ b/bfd/elf32-sh.c
+@@ -2925,7 +2925,7 @@ allocate_dynrelocs (struct elf_link_hash
+    It's a convenient place to determine the PLT style.  */
+ 
+ static bool
+-sh_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++sh_elf_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   sh_elf_hash_table (info)->plt_info = get_plt_info (output_bfd,
+ 						     bfd_link_pic (info));
+@@ -2940,8 +2940,8 @@ sh_elf_always_size_sections (bfd *output
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			      struct bfd_link_info *info)
++sh_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			   struct bfd_link_info *info)
+ {
+   struct elf_sh_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2954,7 +2954,8 @@ sh_elf_size_dynamic_sections (bfd *outpu
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -6598,10 +6599,8 @@ sh_elf_encode_eh_address (bfd *abfd,
+ 					sh_elf_link_hash_table_create
+ #define elf_backend_adjust_dynamic_symbol \
+ 					sh_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					sh_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					sh_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	sh_elf_early_size_sections
++#define elf_backend_late_size_sections	sh_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym	sh_elf_omit_section_dynsym
+ #define elf_backend_finish_dynamic_symbol \
+ 					sh_elf_finish_dynamic_symbol
+--- a/bfd/elf32-sparc.c
++++ b/bfd/elf32-sparc.c
+@@ -248,8 +248,7 @@ elf32_sparc_reloc_type_class (const stru
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_sparc_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	_bfd_sparc_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_sparc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	_bfd_sparc_elf_late_size_sections
+ #define elf_backend_relocate_section	_bfd_sparc_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+ 					_bfd_sparc_elf_finish_dynamic_symbol
+--- a/bfd/elf32-tic6x.c
++++ b/bfd/elf32-tic6x.c
+@@ -3160,7 +3160,7 @@ elf32_tic6x_allocate_dynrelocs (struct e
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_tic6x_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf32_tic6x_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf32_tic6x_link_hash_table *htab;
+   bfd *dynobj;
+@@ -3171,7 +3171,7 @@ elf32_tic6x_size_dynamic_sections (bfd *
+   htab = elf32_tic6x_hash_table (info);
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3358,7 +3358,7 @@ elf32_tic6x_size_dynamic_sections (bfd *
+    and the input sections have been assigned to output sections.  */
+ 
+ static bool
+-elf32_tic6x_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf32_tic6x_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (elf32_tic6x_using_dsbt (output_bfd) && !bfd_link_relocatable (info)
+       && !bfd_elf_stack_segment_size (output_bfd, info,
+@@ -4261,10 +4261,10 @@ elf32_tic6x_write_section (bfd *output_b
+ #define elf_backend_relocs_compatible	_bfd_elf_relocs_compatible
+ #define elf_backend_finish_dynamic_symbol \
+   elf32_tic6x_finish_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-  elf32_tic6x_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  elf32_tic6x_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  elf32_tic6x_early_size_sections
++#define elf_backend_late_size_sections \
++  elf32_tic6x_late_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   elf32_tic6x_finish_dynamic_sections
+ #define bfd_elf32_bfd_final_link \
+--- a/bfd/elf32-tilegx.c
++++ b/bfd/elf32-tilegx.c
+@@ -105,7 +105,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_I
+ #define elf_backend_check_relocs	     tilegx_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilegx_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilegx_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilegx_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilegx_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilegx_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilegx_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilegx_elf_finish_dynamic_sections
+--- a/bfd/elf32-tilepro.c
++++ b/bfd/elf32-tilepro.c
+@@ -2182,11 +2182,9 @@ tilepro_elf_omit_section_dynsym (bfd *ou
+ #define ELF32_DYNAMIC_INTERPRETER "/lib/ld.so.1"
+ 
+ static bool
+-tilepro_elf_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++tilepro_elf_late_size_sections (bfd *output_bfd,
++				struct bfd_link_info *info)
+ {
+-  (void)output_bfd;
+-
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+   asection *s;
+@@ -2195,7 +2193,8 @@ tilepro_elf_size_dynamic_sections (bfd *
+   htab = tilepro_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3739,7 +3738,7 @@ tilepro_additional_program_headers (bfd
+ #define elf_backend_check_relocs	     tilepro_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilepro_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilepro_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilepro_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilepro_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilepro_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilepro_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilepro_elf_finish_dynamic_sections
+--- a/bfd/elf32-vax.c
++++ b/bfd/elf32-vax.c
+@@ -36,7 +36,6 @@ static bool elf_vax_check_relocs (bfd *,
+ 				  asection *, const Elf_Internal_Rela *);
+ static bool elf_vax_adjust_dynamic_symbol (struct bfd_link_info *,
+ 					   struct elf_link_hash_entry *);
+-static bool elf_vax_size_dynamic_sections (bfd *, struct bfd_link_info *);
+ static int elf_vax_relocate_section (bfd *, struct bfd_link_info *,
+ 				     bfd *, asection *, bfd_byte *,
+ 				     Elf_Internal_Rela *,
+@@ -985,8 +984,8 @@ elf_vax_discard_got_entries (struct elf_
+ /* Discard unused dynamic data if this is a static link.  */
+ 
+ static bool
+-elf_vax_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			      struct bfd_link_info *info)
++elf_vax_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -1024,14 +1023,15 @@ elf_vax_always_size_sections (bfd *outpu
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_vax_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf_vax_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -1861,10 +1861,8 @@ elf_vax_plt_sym_val (bfd_vma i, const as
+ #define elf_backend_check_relocs	elf_vax_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf_vax_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					elf_vax_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					elf_vax_size_dynamic_sections
++#define elf_backend_early_size_sections	elf_vax_early_size_sections
++#define elf_backend_late_size_sections	elf_vax_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	elf_vax_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf32-xstormy16.c
++++ b/bfd/elf32-xstormy16.c
+@@ -706,8 +706,8 @@ xstormy16_elf_relax_section (bfd *dynobj
+ }
+ 
+ static bool
+-xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				    struct bfd_link_info *info)
++xstormy16_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				   struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -1013,8 +1013,8 @@ xstormy16_elf_gc_mark_hook (asection *se
+ #define elf_backend_relocate_section		xstormy16_elf_relocate_section
+ #define elf_backend_gc_mark_hook		xstormy16_elf_gc_mark_hook
+ #define elf_backend_check_relocs		xstormy16_elf_check_relocs
+-#define elf_backend_always_size_sections \
+-  xstormy16_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  xstormy16_elf_early_size_sections
+ #define elf_backend_omit_section_dynsym \
+   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_sections \
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -1557,8 +1557,8 @@ elf_xtensa_allocate_local_got_size (stru
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf_xtensa_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf_xtensa_link_hash_table *htab;
+   bfd *dynobj, *abfd;
+@@ -1575,7 +1575,7 @@ elf_xtensa_size_dynamic_sections (bfd *o
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+   srelgot = htab->elf.srelgot;
+   srelplt = htab->elf.srelplt;
+ 
+@@ -1780,8 +1780,7 @@ elf_xtensa_size_dynamic_sections (bfd *o
+ }
+ 
+ static bool
+-elf_xtensa_always_size_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++elf_xtensa_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf_xtensa_link_hash_table *htab;
+   asection *tls_sec;
+@@ -11537,8 +11536,8 @@ static const struct bfd_elf_special_sect
+ #define elf_backend_object_p		     elf_xtensa_object_p
+ #define elf_backend_reloc_type_class	     elf_xtensa_reloc_type_class
+ #define elf_backend_relocate_section	     elf_xtensa_relocate_section
+-#define elf_backend_size_dynamic_sections    elf_xtensa_size_dynamic_sections
+-#define elf_backend_always_size_sections     elf_xtensa_always_size_sections
++#define elf_backend_late_size_sections	     elf_xtensa_late_size_sections
++#define elf_backend_early_size_sections	     elf_xtensa_early_size_sections
+ #define elf_backend_omit_section_dynsym      _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_special_sections	     elf_xtensa_special_sections
+ #define elf_backend_action_discarded	     elf_xtensa_action_discarded
+--- a/bfd/elf64-alpha.c
++++ b/bfd/elf64-alpha.c
+@@ -2579,8 +2579,8 @@ elf64_alpha_size_plt_section (struct bfd
+ }
+ 
+ static bool
+-elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf64_alpha_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				 struct bfd_link_info *info)
+ {
+   bfd *i;
+   struct alpha_elf_link_hash_table * htab;
+@@ -2806,8 +2806,8 @@ elf64_alpha_size_rela_got_section (struc
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				   struct bfd_link_info *info)
++elf64_alpha_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -2819,7 +2819,8 @@ elf64_alpha_size_dynamic_sections (bfd *
+     return false;
+ 
+   dynobj = elf_hash_table(info)->dynobj;
+-  BFD_ASSERT(dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5465,10 +5466,10 @@ static const struct elf_size_info alpha_
+   elf64_alpha_merge_symbol_attribute
+ #define elf_backend_copy_indirect_symbol \
+   elf64_alpha_copy_indirect_symbol
+-#define elf_backend_always_size_sections \
+-  elf64_alpha_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  elf64_alpha_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  elf64_alpha_early_size_sections
++#define elf_backend_late_size_sections \
++  elf64_alpha_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elf64-hppa.c
++++ b/bfd/elf64-hppa.c
+@@ -176,9 +176,6 @@ static bool elf64_hppa_adjust_dynamic_sy
+ static bool elf64_hppa_mark_milli_and_exported_functions
+   (struct elf_link_hash_entry *, void *);
+ 
+-static bool elf64_hppa_size_dynamic_sections
+-  (bfd *, struct bfd_link_info *);
+-
+ static int elf64_hppa_link_output_symbol_hook
+   (struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+    asection *, struct elf_link_hash_entry *);
+@@ -1520,7 +1517,7 @@ elf64_hppa_mark_milli_and_exported_funct
+    the contents of our special sections.  */
+ 
+ static bool
+-elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf64_hppa_link_hash_table *hppa_info;
+   struct elf64_hppa_allocate_data data;
+@@ -1534,7 +1531,8 @@ elf64_hppa_size_dynamic_sections (bfd *o
+     return false;
+ 
+   dynobj = hppa_info->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   /* Mark each function this program exports so that we will allocate
+      space in the .opd section for each function's FPTR.  If we are
+@@ -3984,8 +3982,7 @@ const struct elf_size_info hppa64_elf_si
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf64_hppa_adjust_dynamic_symbol
+ 
+-#define elf_backend_size_dynamic_sections \
+-					elf64_hppa_size_dynamic_sections
++#define elf_backend_late_size_sections	elf64_hppa_late_size_sections
+ 
+ #define elf_backend_finish_dynamic_symbol \
+ 					elf64_hppa_finish_dynamic_symbol
+--- a/bfd/elf64-ia64-vms.c
++++ b/bfd/elf64-ia64-vms.c
+@@ -2590,8 +2590,8 @@ elf64_ia64_adjust_dynamic_symbol (struct
+ }
+ 
+ static bool
+-elf64_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf64_ia64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf64_ia64_allocate_data data;
+   struct elf64_ia64_link_hash_table *ia64_info;
+@@ -2600,11 +2600,12 @@ elf64_ia64_size_dynamic_sections (bfd *o
+   struct elf_link_hash_table *hash_table;
+ 
+   hash_table = elf_hash_table (info);
+-  dynobj = hash_table->dynobj;
+   ia64_info = elf64_ia64_hash_table (info);
+   if (ia64_info == NULL)
+     return false;
+-  BFD_ASSERT(dynobj != NULL);
++  dynobj = hash_table->dynobj;
++  if (dynobj == NULL)
++    return true;
+   data.info = info;
+ 
+   /* Allocate the GOT entries.  */
+@@ -5484,8 +5485,8 @@ static const struct elf_size_info elf64_
+ 	elf64_ia64_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 	elf64_ia64_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elf64_ia64_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elf64_ia64_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elf64-mips.c
++++ b/bfd/elf64-mips.c
+@@ -4745,10 +4745,10 @@ const struct elf_size_info mips_elf64_si
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 				_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-				_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-				_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections \
++				_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections \
++				_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section    _bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf64-ppc.c
++++ b/bfd/elf64-ppc.c
+@@ -118,8 +118,8 @@ static bfd_vma opd_entry_value
+ #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
+ #define elf_backend_hide_symbol		      ppc64_elf_hide_symbol
+ #define elf_backend_maybe_function_sym	      ppc64_elf_maybe_function_sym
+-#define elf_backend_always_size_sections      ppc64_elf_edit
+-#define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	      ppc64_elf_edit
++#define elf_backend_late_size_sections	      ppc64_elf_late_size_sections
+ #define elf_backend_hash_symbol		      ppc64_elf_hash_symbol
+ #define elf_backend_init_index_section	      _bfd_elf_init_2_index_sections
+ #define elf_backend_action_discarded	      ppc64_elf_action_discarded
+@@ -10118,7 +10118,7 @@ allocate_dynrelocs (struct elf_link_hash
+   ((((v) & 0x3ffff0000ULL) << 16) | (v & 0xffff))
+ #define HA34(v) ((v + (1ULL << 33)) >> 34)
+ 
+-/* Called via elf_link_hash_traverse from ppc64_elf_size_dynamic_sections
++/* Called via elf_link_hash_traverse from ppc64_elf_late_size_sections
+    to set up space for global entry stubs.  These are put in glink,
+    after the branch table.  */
+ 
+@@ -10195,8 +10195,8 @@ size_global_entry_stubs (struct elf_link
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-ppc64_elf_size_dynamic_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++ppc64_elf_late_size_sections (bfd *output_bfd,
++			      struct bfd_link_info *info)
+ {
+   struct ppc_link_hash_table *htab;
+   bfd *dynobj;
+@@ -10211,7 +10211,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
+ 
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+--- a/bfd/elf64-s390.c
++++ b/bfd/elf64-s390.c
+@@ -1301,7 +1301,7 @@ elf_s390_gc_mark_hook (asection *sec,
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_s390_size_dynamic_sections if no dynamic sections will be
++   or elf_s390_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static void
+@@ -1714,8 +1714,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_s390_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1729,7 +1729,7 @@ elf_s390_size_dynamic_sections (bfd *out
+ 
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3912,7 +3912,7 @@ const struct elf_size_info s390_elf64_si
+ #define elf_backend_gc_mark_hook	      elf_s390_gc_mark_hook
+ #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
+ #define elf_backend_relocate_section	      elf_s390_relocate_section
+-#define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
++#define elf_backend_late_size_sections	      elf_s390_late_size_sections
+ #define elf_backend_init_index_section	      _bfd_elf_init_1_index_section
+ #define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
+ #define elf_backend_grok_psinfo		      elf_s390_grok_psinfo
+--- a/bfd/elf64-sparc.c
++++ b/bfd/elf64-sparc.c
+@@ -953,8 +953,8 @@ const struct elf_size_info elf64_sparc_s
+   _bfd_sparc_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym \
+   _bfd_sparc_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_sparc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_sparc_elf_late_size_sections
+ #define elf_backend_relocate_section \
+   _bfd_sparc_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf64-tilegx.c
++++ b/bfd/elf64-tilegx.c
+@@ -106,7 +106,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_I
+ #define elf_backend_check_relocs	     tilegx_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilegx_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilegx_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilegx_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilegx_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilegx_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilegx_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilegx_elf_finish_dynamic_sections
+--- a/bfd/elf64-x86-64.c
++++ b/bfd/elf64-x86-64.c
+@@ -2456,8 +2456,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struc
+ }
+ 
+ static bool
+-elf_x86_64_always_size_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++elf_x86_64_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *abfd;
+ 
+@@ -2470,7 +2469,7 @@ elf_x86_64_always_size_sections (bfd *ou
+ 					     elf_x86_64_scan_relocs))
+       return false;
+ 
+-  return _bfd_x86_elf_always_size_sections (output_bfd, info);
++  return _bfd_x86_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ /* Return the relocation value for @tpoff relocation
+@@ -5384,7 +5383,7 @@ elf_x86_64_special_sections[]=
+   elf_x86_64_reloc_name_lookup
+ 
+ #define elf_backend_relocs_compatible	    elf_x86_64_relocs_compatible
+-#define elf_backend_always_size_sections    elf_x86_64_always_size_sections
++#define elf_backend_early_size_sections	    elf_x86_64_early_size_sections
+ #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol   elf_x86_64_finish_dynamic_symbol
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -6619,8 +6619,8 @@ bfd_elf_size_dynamic_sections (bfd *outp
+ 
+   /* The backend may have to create some sections regardless of whether
+      we're dynamic or not.  */
+-  if (bed->elf_backend_always_size_sections
+-      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
++  if (bed->elf_backend_early_size_sections
++      && !bed->elf_backend_early_size_sections (output_bfd, info))
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+@@ -7400,9 +7400,8 @@ NOTE: This behaviour is deprecated and w
+ 
+   /* The backend must work out the sizes of all the other dynamic
+      sections.  */
+-  if (dynobj != NULL
+-      && bed->elf_backend_size_dynamic_sections != NULL
+-      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
++  if (bed->elf_backend_late_size_sections != NULL
++      && !bed->elf_backend_late_size_sections (output_bfd, info))
+     return false;
+ 
+   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+--- a/bfd/elfn32-mips.c
++++ b/bfd/elfn32-mips.c
+@@ -4131,10 +4131,8 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elfnn-aarch64.c
++++ b/bfd/elfnn-aarch64.c
+@@ -112,7 +112,7 @@
+   allocate space for one relocation on the slot. Record the GOT offset
+   for this symbol.
+ 
+-  elfNN_aarch64_size_dynamic_sections ()
++  elfNN_aarch64_late_size_sections ()
+ 
+   Iterate all input BFDS, look for in the local symbol data structure
+   constructed earlier for local TLS symbols and allocate them double
+@@ -8976,8 +8976,8 @@ elfNN_aarch64_allocate_local_ifunc_dynre
+    though !  */
+ 
+ static bool
+-elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				     struct bfd_link_info *info)
++elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				  struct bfd_link_info *info)
+ {
+   struct elf_aarch64_link_hash_table *htab;
+   bfd *dynobj;
+@@ -8988,7 +8988,8 @@ elfNN_aarch64_size_dynamic_sections (bfd
+   htab = elf_aarch64_hash_table ((info));
+   dynobj = htab->root.dynobj;
+ 
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -9390,8 +9391,8 @@ elfNN_aarch64_create_small_pltn_entry (s
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bool
+-elfNN_aarch64_always_size_sections (bfd *output_bfd,
+-				    struct bfd_link_info *info)
++elfNN_aarch64_early_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+ 
+@@ -10126,8 +10127,8 @@ const struct elf_size_info elfNN_aarch64
+ #define elf_backend_adjust_dynamic_symbol	\
+   elfNN_aarch64_adjust_dynamic_symbol
+ 
+-#define elf_backend_always_size_sections	\
+-  elfNN_aarch64_always_size_sections
++#define elf_backend_early_size_sections		\
++  elfNN_aarch64_early_size_sections
+ 
+ #define elf_backend_check_relocs		\
+   elfNN_aarch64_check_relocs
+@@ -10182,8 +10183,8 @@ const struct elf_size_info elfNN_aarch64
+ #define elf_backend_modify_headers		\
+   elfNN_aarch64_modify_headers
+ 
+-#define elf_backend_size_dynamic_sections	\
+-  elfNN_aarch64_size_dynamic_sections
++#define elf_backend_late_size_sections		\
++  elfNN_aarch64_late_size_sections
+ 
+ #define elf_backend_size_info			\
+   elfNN_aarch64_size_info
+--- a/bfd/elfnn-ia64.c
++++ b/bfd/elfnn-ia64.c
+@@ -2986,8 +2986,8 @@ elfNN_ia64_adjust_dynamic_symbol (struct
+ }
+ 
+ static bool
+-elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elfNN_ia64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elfNN_ia64_allocate_data data;
+   struct elfNN_ia64_link_hash_table *ia64_info;
+@@ -2998,8 +2998,9 @@ elfNN_ia64_size_dynamic_sections (bfd *o
+   if (ia64_info == NULL)
+     return false;
+   dynobj = ia64_info->root.dynobj;
++  if (dynobj == NULL)
++    return true;
+   ia64_info->self_dtpmod_offset = (bfd_vma) -1;
+-  BFD_ASSERT(dynobj != NULL);
+   data.info = info;
+ 
+   /* Set the contents of the .interp section to the interpreter.  */
+@@ -5035,8 +5036,8 @@ ignore_errors (const char *fmt ATTRIBUTE
+ 	elfNN_ia64_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 	elfNN_ia64_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elfNN_ia64_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elfNN_ia64_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elfnn-loongarch.c
++++ b/bfd/elfnn-loongarch.c
+@@ -1574,8 +1574,8 @@ maybe_set_textrel (struct elf_link_hash_
+ }
+ 
+ static bool
+-loongarch_elf_size_dynamic_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++loongarch_elf_late_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   struct loongarch_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1585,7 +1585,8 @@ loongarch_elf_size_dynamic_sections (bfd
+   htab = loongarch_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -4140,7 +4141,7 @@ elf_loongarch64_hash_symbol (struct elf_
+   loongarch_elf_create_dynamic_sections
+ #define elf_backend_check_relocs loongarch_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
++#define elf_backend_late_size_sections loongarch_elf_late_size_sections
+ #define elf_backend_relocate_section loongarch_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections				   \
+--- a/bfd/elfnn-riscv.c
++++ b/bfd/elfnn-riscv.c
+@@ -1348,7 +1348,7 @@ allocate_local_ifunc_dynrelocs (void **s
+ }
+ 
+ static bool
+-riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++riscv_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct riscv_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1358,7 +1358,8 @@ riscv_elf_size_dynamic_sections (bfd *ou
+   htab = riscv_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5341,7 +5342,7 @@ riscv_elf_merge_symbol_attribute (struct
+ #define elf_backend_create_dynamic_sections	riscv_elf_create_dynamic_sections
+ #define elf_backend_check_relocs		riscv_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol	riscv_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	riscv_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		riscv_elf_late_size_sections
+ #define elf_backend_relocate_section		riscv_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol	riscv_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	riscv_elf_finish_dynamic_sections
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -9619,8 +9619,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
+    check for any mips16 stub sections that we can discard.  */
+ 
+ bool
+-_bfd_mips_elf_always_size_sections (bfd *output_bfd,
+-				    struct bfd_link_info *info)
++_bfd_mips_elf_early_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   asection *sect;
+   struct mips_elf_link_hash_table *htab;
+@@ -9963,8 +9963,8 @@ mips_elf_set_plt_sym_value (struct mips_
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++_bfd_mips_elf_late_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s, *sreldyn;
+@@ -9974,7 +9974,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd
+   htab = mips_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -14899,7 +14900,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_always_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+@@ -14958,7 +14959,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_always_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+--- a/bfd/elfxx-mips.h
++++ b/bfd/elfxx-mips.h
+@@ -61,9 +61,9 @@ extern bool _bfd_mips_elf_check_relocs
+   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+ extern bool _bfd_mips_elf_adjust_dynamic_symbol
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+-extern bool _bfd_mips_elf_always_size_sections
++extern bool _bfd_mips_elf_early_size_sections
+   (bfd *, struct bfd_link_info *);
+-extern bool _bfd_mips_elf_size_dynamic_sections
++extern bool _bfd_mips_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern int _bfd_mips_elf_relocate_section
+   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+--- a/bfd/elfxx-sparc.c
++++ b/bfd/elfxx-sparc.c
+@@ -2381,8 +2381,8 @@ _bfd_sparc_elf_omit_section_dynsym (bfd
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++_bfd_sparc_elf_late_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   struct _bfd_sparc_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2392,7 +2392,8 @@ _bfd_sparc_elf_size_dynamic_sections (bf
+   htab = _bfd_sparc_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+--- a/bfd/elfxx-sparc.h
++++ b/bfd/elfxx-sparc.h
+@@ -117,7 +117,7 @@ extern bool _bfd_sparc_elf_adjust_dynami
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+ extern bool _bfd_sparc_elf_omit_section_dynsym
+   (bfd *, struct bfd_link_info *, asection *);
+-extern bool _bfd_sparc_elf_size_dynamic_sections
++extern bool _bfd_sparc_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern bool _bfd_sparc_elf_new_section_hook
+   (bfd *, asection *);
+--- a/bfd/elfxx-target.h
++++ b/bfd/elfxx-target.h
+@@ -487,11 +487,11 @@
+ #ifndef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol 0
+ #endif
+-#ifndef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections 0
++#ifndef elf_backend_early_size_sections
++#define elf_backend_early_size_sections 0
+ #endif
+-#ifndef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections 0
++#ifndef elf_backend_late_size_sections
++#define elf_backend_late_size_sections 0
+ #endif
+ #ifndef elf_backend_strip_zero_sized_dynamic_sections
+ #define elf_backend_strip_zero_sized_dynamic_sections 0
+@@ -849,8 +849,8 @@ static const struct elf_backend_data elf
+   elf_backend_check_directives,
+   elf_backend_notice_as_needed,
+   elf_backend_adjust_dynamic_symbol,
+-  elf_backend_always_size_sections,
+-  elf_backend_size_dynamic_sections,
++  elf_backend_early_size_sections,
++  elf_backend_late_size_sections,
+   elf_backend_strip_zero_sized_dynamic_sections,
+   elf_backend_init_index_section,
+   elf_backend_relocate_section,
+--- a/bfd/elfxx-tilegx.c
++++ b/bfd/elfxx-tilegx.c
+@@ -2430,8 +2430,8 @@ tilegx_elf_omit_section_dynsym (bfd *out
+ }
+ 
+ bool
+-tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++tilegx_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct tilegx_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2441,7 +2441,8 @@ tilegx_elf_size_dynamic_sections (bfd *o
+   htab = tilegx_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+--- a/bfd/elfxx-tilegx.h
++++ b/bfd/elfxx-tilegx.h
+@@ -57,7 +57,7 @@ tilegx_elf_omit_section_dynsym (bfd *,
+ 				asection *);
+ 
+ extern bool
+-tilegx_elf_size_dynamic_sections (bfd *, struct bfd_link_info *);
++tilegx_elf_late_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern int
+ tilegx_elf_relocate_section (bfd *, struct bfd_link_info *,
+--- a/bfd/elfxx-x86.c
++++ b/bfd/elfxx-x86.c
+@@ -2225,7 +2225,7 @@ _bfd_elf_x86_valid_reloc_p (asection *in
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
++_bfd_x86_elf_late_size_sections (bfd *output_bfd,
+ 				    struct bfd_link_info *info)
+ {
+   struct elf_x86_link_hash_table *htab;
+@@ -2241,7 +2241,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd
+     return false;
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   /* Set up .got offsets for local syms, and space for local dynamic
+      relocs.  */
+@@ -2948,8 +2948,8 @@ _bfd_x86_elf_finish_dynamic_sections (bf
+ 
+ 
+ bool
+-_bfd_x86_elf_always_size_sections (bfd *output_bfd,
+-				   struct bfd_link_info *info)
++_bfd_x86_elf_early_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   asection *tls_sec = elf_hash_table (info)->tls_sec;
+ 
+--- a/bfd/elfxx-x86.h
++++ b/bfd/elfxx-x86.h
+@@ -854,13 +854,13 @@ extern bool _bfd_elf_x86_valid_reloc_p
+    const Elf_Internal_Rela *, struct elf_link_hash_entry *,
+    Elf_Internal_Sym *, Elf_Internal_Shdr *, bool *);
+ 
+-extern bool _bfd_x86_elf_size_dynamic_sections
++extern bool _bfd_x86_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ 
+ extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections
+   (bfd *, struct bfd_link_info *);
+ 
+-extern bool _bfd_x86_elf_always_size_sections
++extern bool _bfd_x86_elf_early_size_sections
+   (bfd *, struct bfd_link_info *);
+ 
+ extern void _bfd_x86_elf_merge_symbol_attribute
+@@ -932,8 +932,8 @@ extern void _bfd_x86_elf_link_report_rel
+ 
+ #define elf_backend_check_relocs \
+   _bfd_x86_elf_check_relocs
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_x86_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_x86_elf_late_size_sections
+ #define elf_backend_merge_symbol_attribute \
+   _bfd_x86_elf_merge_symbol_attribute
+ #define elf_backend_copy_indirect_symbol \
+--- a/ld/emultempl/vms.em
++++ b/ld/emultempl/vms.em
+@@ -196,10 +196,9 @@ gld${EMULATION_NAME}_before_allocation (
+ 
+   /* The backend must work out the sizes of all the other dynamic
+      sections.  */
+-  if (elf_hash_table (&link_info)->dynamic_sections_created
+-      && bed->elf_backend_size_dynamic_sections
+-      && ! (*bed->elf_backend_size_dynamic_sections) (link_info.output_bfd,
+-						      &link_info))
++  if (bed->elf_backend_late_size_sections
++      && !bed->elf_backend_late_size_sections (link_info.output_bfd,
++					       &link_info))
+     einfo (_("%F%P: failed to set dynamic section sizes: %E\n"));
+ 
+   before_allocation_default ();
diff --git a/toolchain/binutils/patches/2.40/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch b/toolchain/binutils/patches/2.40/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch
new file mode 100644
index 0000000..8e5f1b7
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch
@@ -0,0 +1,218 @@
+From 3c6c32951e292a51ede70b8087bb0308d7dbc4fc Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Thu, 28 Mar 2024 20:33:32 +1030
+Subject: [PATCH 2/2] PR 30569, delete _bfd_mips_elf_early_size_sections
+
+PR30569 was triggered by a patch of mine 6540edd52cc0 moving the call
+to always_size_sections in bfd_elf_size_dynamic_sections earlier, made
+to support the x86 DT_RELR implementation.  This broke mips16 code
+handling stubs when --export-dynamic is passed to the linker, because
+numerous symbols then became dynamic after always_size_sections.  The
+mips backend fiddles with symbols in its always_size_sections.  Maciej
+in 902e9fc76a0e had moved the call to always_size_sections to after
+the export-dynamic code.  Prior to that, Nathan in 04c3a75556c0 moved
+it before the exec stack code, back to the start of
+bfd_elf_size_dynamic_sections which was where Ian put it originally
+in ff12f303355b.  So the call has moved around a little.  I'm leaving
+it where it is, and instead calling mips_elf_check_symbols from
+late_size_sections (the old size_dynamic_sections) which is now always
+called.  In fact, the whole of _bfd_mips_elf_early_size_sections can
+be merged into _bfd_mips_elf_late_size_sections.
+---
+ bfd/elf32-mips.c  |  1 -
+ bfd/elf64-mips.c  |  2 --
+ bfd/elfn32-mips.c |  1 -
+ bfd/elfxx-mips.c  | 84 +++++++++++++++++++----------------------------
+ bfd/elfxx-mips.h  |  2 --
+ 5 files changed, 34 insertions(+), 56 deletions(-)
+
+--- a/bfd/elf32-mips.c
++++ b/bfd/elf32-mips.c
+@@ -2534,7 +2534,6 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+--- a/bfd/elf64-mips.c
++++ b/bfd/elf64-mips.c
+@@ -4745,8 +4745,6 @@ const struct elf_size_info mips_elf64_si
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 				_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections \
+-				_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections \
+ 				_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+--- a/bfd/elfn32-mips.c
++++ b/bfd/elfn32-mips.c
+@@ -4131,7 +4131,6 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -9614,48 +9614,6 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
+   return _bfd_elf_adjust_dynamic_copy (info, h, s);
+ }
+ 
+-/* This function is called after all the input files have been read,
+-   and the input sections have been assigned to output sections.  We
+-   check for any mips16 stub sections that we can discard.  */
+-
+-bool
+-_bfd_mips_elf_early_size_sections (bfd *output_bfd,
+-				   struct bfd_link_info *info)
+-{
+-  asection *sect;
+-  struct mips_elf_link_hash_table *htab;
+-  struct mips_htab_traverse_info hti;
+-
+-  htab = mips_elf_hash_table (info);
+-  BFD_ASSERT (htab != NULL);
+-
+-  /* The .reginfo section has a fixed size.  */
+-  sect = bfd_get_section_by_name (output_bfd, ".reginfo");
+-  if (sect != NULL)
+-    {
+-      bfd_set_section_size (sect, sizeof (Elf32_External_RegInfo));
+-      sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
+-    }
+-
+-  /* The .MIPS.abiflags section has a fixed size.  */
+-  sect = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
+-  if (sect != NULL)
+-    {
+-      bfd_set_section_size (sect, sizeof (Elf_External_ABIFlags_v0));
+-      sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
+-    }
+-
+-  hti.info = info;
+-  hti.output_bfd = output_bfd;
+-  hti.error = false;
+-  mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+-			       mips_elf_check_symbols, &hti);
+-  if (hti.error)
+-    return false;
+-
+-  return true;
+-}
+-
+ /* If the link uses a GOT, lay it out and work out its size.  */
+ 
+ static bool
+@@ -9960,7 +9918,8 @@ mips_elf_set_plt_sym_value (struct mips_
+   return true;
+ }
+ 
+-/* Set the sizes of the dynamic sections.  */
++/* Set the sizes of the dynamic sections, some mips non-dynamic sections,
++   and check for any mips16 stub sections that we can discard.  */
+ 
+ bool
+ _bfd_mips_elf_late_size_sections (bfd *output_bfd,
+@@ -9970,14 +9929,39 @@ _bfd_mips_elf_late_size_sections (bfd *o
+   asection *s, *sreldyn;
+   bool reltext;
+   struct mips_elf_link_hash_table *htab;
++  struct mips_htab_traverse_info hti;
+ 
+   htab = mips_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+-  dynobj = elf_hash_table (info)->dynobj;
++
++  /* The .reginfo section has a fixed size.  */
++  s = bfd_get_section_by_name (output_bfd, ".reginfo");
++  if (s != NULL)
++    {
++      bfd_set_section_size (s, sizeof (Elf32_External_RegInfo));
++      s->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
++    }
++
++  /* The .MIPS.abiflags section has a fixed size.  */
++  s = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
++  if (s != NULL)
++    {
++      bfd_set_section_size (s, sizeof (Elf_External_ABIFlags_v0));
++      s->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
++    }
++
++  hti.info = info;
++  hti.output_bfd = output_bfd;
++  hti.error = false;
++  mips_elf_link_hash_traverse (htab, mips_elf_check_symbols, &hti);
++  if (hti.error)
++    return false;
++
++  dynobj = htab->root.dynobj;
+   if (dynobj == NULL)
+     return true;
+ 
+-  if (elf_hash_table (info)->dynamic_sections_created)
++  if (htab->root.dynamic_sections_created)
+     {
+       /* Set the contents of the .interp section to the interpreter.  */
+       if (bfd_link_executable (info) && !info->nointerp)
+@@ -10117,7 +10101,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	    }
+ 	}
+       else if (bfd_link_executable (info)
+-	       && ! mips_elf_hash_table (info)->use_rld_obj_head
++	       && !htab->use_rld_obj_head
+ 	       && startswith (name, ".rld_map"))
+ 	{
+ 	  /* We add a room for __rld_map.  It will be filled in by the
+@@ -10126,7 +10110,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	}
+       else if (SGI_COMPAT (output_bfd)
+ 	       && startswith (name, ".compact_rel"))
+-	s->size += mips_elf_hash_table (info)->compact_rel_size;
++	s->size += htab->compact_rel_size;
+       else if (s == htab->root.splt)
+ 	{
+ 	  /* If the last PLT entry has a branch delay slot, allocate
+@@ -10166,7 +10150,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	}
+     }
+ 
+-  if (elf_hash_table (info)->dynamic_sections_created)
++  if (htab->root.dynamic_sections_created)
+     {
+       /* Add some entries to the .dynamic section.  We fill in the
+ 	 values later, in _bfd_mips_elf_finish_dynamic_sections, but we
+@@ -14900,7 +14884,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_late_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+@@ -14959,7 +14943,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_late_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+--- a/bfd/elfxx-mips.h
++++ b/bfd/elfxx-mips.h
+@@ -61,8 +61,6 @@ extern bool _bfd_mips_elf_check_relocs
+   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+ extern bool _bfd_mips_elf_adjust_dynamic_symbol
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+-extern bool _bfd_mips_elf_early_size_sections
+-  (bfd *, struct bfd_link_info *);
+ extern bool _bfd_mips_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern int _bfd_mips_elf_relocate_section
diff --git a/toolchain/binutils/patches/2.40/005-libctf-update-regexp-to-allow-makeinfo-to-build-docu.patch b/toolchain/binutils/patches/2.40/005-libctf-update-regexp-to-allow-makeinfo-to-build-docu.patch
new file mode 100644
index 0000000..19af340
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/005-libctf-update-regexp-to-allow-makeinfo-to-build-docu.patch
@@ -0,0 +1,70 @@
+From f7c5db99b76e8dde89335d794c82fcbfbf53c612 Mon Sep 17 00:00:00 2001
+From: Enze Li <enze.li@hotmail.com>
+Date: Sat, 14 Jan 2023 11:33:48 +0800
+Subject: [PATCH 05/50] libctf: update regexp to allow makeinfo to build
+ document
+
+While trying to build gdb on latest openSUSE Tumbleweed, I noticed the
+following warning,
+
+ checking for makeinfo... makeinfo --split-size=5000000
+ configure: WARNING:
+ *** Makeinfo is too old. Info documentation will not be built.
+
+then I checked the version of makeinfo, it said,
+======
+$ makeinfo --version
+texi2any (GNU texinfo) 7.0.1
+
+Copyright (C) 2022 Free Software Foundation, Inc.
+License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
+This is free software: you are free to change and redistribute it.
+There is NO WARRANTY, to the extent permitted by law.
+======
+
+After digging a little bit, it became quite obvious that a dot is
+missing in regexp that makes it impossible to match versions higher than
+7.0, and here's the solution:
+
+-       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9][0-9])' >/dev/null 2>&1; then
++       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9]\.[0-9])' >/dev/null 2>&1; then
+
+However, Eli pointed out that the solution above has another problem: it
+will stop working when Texinfo 10.1 will be released.  Meanwhile, he
+suggested to solve this problem permanently.  That is, we don't care
+about the minor version for Texinfo > 6.9, we only care about the major
+version.
+
+In this way, the problem will be resolved permanently, thanks to Eli.
+
+libctf/ChangeLog:
+
+	* configure: Regenerated.
+	* configure.ac: Update regexp to match versions higher than 7.0.
+---
+ libctf/configure    | 2 +-
+ libctf/configure.ac | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/libctf/configure
++++ b/libctf/configure
+@@ -14865,7 +14865,7 @@ esac
+     # We require texinfo to be 6.3 or later, for a working synindex
+     # and validatemenus: otherwise we fall back to /bin/true.
+     if ${MAKEINFO} --version \
+-       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9][0-9])' >/dev/null 2>&1; then
++       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9]|[1-6][0-9])' >/dev/null 2>&1; then
+       build_info=yes
+     else
+         build_info=
+--- a/libctf/configure.ac
++++ b/libctf/configure.ac
+@@ -184,7 +184,7 @@ changequote(,)
+     # We require texinfo to be 6.3 or later, for a working synindex
+     # and validatemenus: otherwise we fall back to /bin/true.
+     if ${MAKEINFO} --version \
+-       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9][0-9])' >/dev/null 2>&1; then
++       | egrep 'texinfo[^0-9]*(6\.[3-9]|[7-9]|[1-6][0-9])' >/dev/null 2>&1; then
+       build_info=yes
+     else
+         build_info=
diff --git a/toolchain/binutils/patches/2.40/007-Fix-version-number-snafu-in-some-configuration-files.patch b/toolchain/binutils/patches/2.40/007-Fix-version-number-snafu-in-some-configuration-files.patch
new file mode 100644
index 0000000..0676240
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/007-Fix-version-number-snafu-in-some-configuration-files.patch
@@ -0,0 +1,444 @@
+From 59706683feafb6252d0ad369cf8759f75fd147be Mon Sep 17 00:00:00 2001
+From: Nick Clifton <nickc@redhat.com>
+Date: Tue, 17 Jan 2023 12:02:56 +0000
+Subject: [PATCH 07/50] Fix version number snafu in some configuration files:
+ 2.40.00 should be 2.40
+
+---
+ binutils/configure             | 20 ++++++++++----------
+ gprof/configure                | 20 ++++++++++----------
+ gprofng/configure              | 20 ++++++++++----------
+ gprofng/doc/version.texi       |  4 ++--
+ gprofng/libcollector/configure | 20 ++++++++++----------
+ ld/configure                   | 20 ++++++++++----------
+ 6 files changed, 52 insertions(+), 52 deletions(-)
+
+--- a/binutils/configure
++++ b/binutils/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for binutils 2.40.00.
++# Generated by GNU Autoconf 2.69 for binutils 2.40.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='binutils'
+ PACKAGE_TARNAME='binutils'
+-PACKAGE_VERSION='2.40.00'
+-PACKAGE_STRING='binutils 2.40.00'
++PACKAGE_VERSION='2.40'
++PACKAGE_STRING='binutils 2.40'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1401,7 +1401,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures binutils 2.40.00 to adapt to many kinds of systems.
++\`configure' configures binutils 2.40 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1472,7 +1472,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of binutils 2.40.00:";;
++     short | recursive ) echo "Configuration of binutils 2.40:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1631,7 +1631,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-binutils configure 2.40.00
++binutils configure 2.40
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2099,7 +2099,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by binutils $as_me 2.40.00, which was
++It was created by binutils $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3081,7 +3081,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='binutils'
+- VERSION='2.40.00'
++ VERSION='2.40'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -15326,7 +15326,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by binutils $as_me 2.40.00, which was
++This file was extended by binutils $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -15392,7 +15392,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-binutils config.status 2.40.00
++binutils config.status 2.40
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprof/configure
++++ b/gprof/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprof 2.40.00.
++# Generated by GNU Autoconf 2.69 for gprof 2.40.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprof'
+ PACKAGE_TARNAME='gprof'
+-PACKAGE_VERSION='2.40.00'
+-PACKAGE_STRING='gprof 2.40.00'
++PACKAGE_VERSION='2.40'
++PACKAGE_STRING='gprof 2.40'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1338,7 +1338,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprof 2.40.00 to adapt to many kinds of systems.
++\`configure' configures gprof 2.40 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1409,7 +1409,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprof 2.40.00:";;
++     short | recursive ) echo "Configuration of gprof 2.40:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1520,7 +1520,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprof configure 2.40.00
++gprof configure 2.40
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -1885,7 +1885,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprof $as_me 2.40.00, which was
++It was created by gprof $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -2864,7 +2864,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprof'
+- VERSION='2.40.00'
++ VERSION='2.40'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -12572,7 +12572,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprof $as_me 2.40.00, which was
++This file was extended by gprof $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -12638,7 +12638,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprof config.status 2.40.00
++gprof config.status 2.40
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprofng/configure
++++ b/gprofng/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprofng 2.40.00.
++# Generated by GNU Autoconf 2.69 for gprofng 2.40.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprofng'
+ PACKAGE_TARNAME='gprofng'
+-PACKAGE_VERSION='2.40.00'
+-PACKAGE_STRING='gprofng 2.40.00'
++PACKAGE_VERSION='2.40'
++PACKAGE_STRING='gprofng 2.40'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1362,7 +1362,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprofng 2.40.00 to adapt to many kinds of systems.
++\`configure' configures gprofng 2.40 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1433,7 +1433,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprofng 2.40.00:";;
++     short | recursive ) echo "Configuration of gprofng 2.40:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1547,7 +1547,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprofng configure 2.40.00
++gprofng configure 2.40
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2079,7 +2079,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprofng $as_me 2.40.00, which was
++It was created by gprofng $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3052,7 +3052,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprofng'
+- VERSION='2.40.00'
++ VERSION='2.40'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -17467,7 +17467,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprofng $as_me 2.40.00, which was
++This file was extended by gprofng $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -17533,7 +17533,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprofng config.status 2.40.00
++gprofng config.status 2.40
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprofng/doc/version.texi
++++ b/gprofng/doc/version.texi
+@@ -1,4 +1,4 @@
+ @set UPDATED 5 January 2023
+ @set UPDATED-MONTH January 2023
+-@set EDITION 2.40.00
+-@set VERSION 2.40.00
++@set EDITION 2.40
++@set VERSION 2.40
+--- a/gprofng/libcollector/configure
++++ b/gprofng/libcollector/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprofng 2.40.00.
++# Generated by GNU Autoconf 2.69 for gprofng 2.40.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprofng'
+ PACKAGE_TARNAME='gprofng'
+-PACKAGE_VERSION='2.40.00'
+-PACKAGE_STRING='gprofng 2.40.00'
++PACKAGE_VERSION='2.40'
++PACKAGE_STRING='gprofng 2.40'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprofng 2.40.00 to adapt to many kinds of systems.
++\`configure' configures gprofng 2.40 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1396,7 +1396,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprofng 2.40.00:";;
++     short | recursive ) echo "Configuration of gprofng 2.40:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1505,7 +1505,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprofng configure 2.40.00
++gprofng configure 2.40
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -1991,7 +1991,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprofng $as_me 2.40.00, which was
++It was created by gprofng $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -2968,7 +2968,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprofng'
+- VERSION='2.40.00'
++ VERSION='2.40'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -16098,7 +16098,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprofng $as_me 2.40.00, which was
++This file was extended by gprofng $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -16164,7 +16164,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprofng config.status 2.40.00
++gprofng config.status 2.40
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/ld/configure
++++ b/ld/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for ld 2.40.00.
++# Generated by GNU Autoconf 2.69 for ld 2.40.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='ld'
+ PACKAGE_TARNAME='ld'
+-PACKAGE_VERSION='2.40.00'
+-PACKAGE_STRING='ld 2.40.00'
++PACKAGE_VERSION='2.40'
++PACKAGE_STRING='ld 2.40'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1423,7 +1423,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures ld 2.40.00 to adapt to many kinds of systems.
++\`configure' configures ld 2.40 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1494,7 +1494,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of ld 2.40.00:";;
++     short | recursive ) echo "Configuration of ld 2.40:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1661,7 +1661,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-ld configure 2.40.00
++ld configure 2.40
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2376,7 +2376,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by ld $as_me 2.40.00, which was
++It was created by ld $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3359,7 +3359,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='ld'
+- VERSION='2.40.00'
++ VERSION='2.40'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -18083,7 +18083,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by ld $as_me 2.40.00, which was
++This file was extended by ld $as_me 2.40, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -18149,7 +18149,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-ld config.status 2.40.00
++ld config.status 2.40
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
diff --git a/toolchain/binutils/patches/2.40/010-toplevel-Makefile.def-add-install-strip-dependency-o.patch b/toolchain/binutils/patches/2.40/010-toplevel-Makefile.def-add-install-strip-dependency-o.patch
new file mode 100644
index 0000000..bef40f5
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/010-toplevel-Makefile.def-add-install-strip-dependency-o.patch
@@ -0,0 +1,60 @@
+From bcea253f5fa194e57f9564e8461c718e228bd26e Mon Sep 17 00:00:00 2001
+From: Indu Bhagat <indu.bhagat@oracle.com>
+Date: Wed, 18 Jan 2023 23:17:49 -0800
+Subject: [PATCH 10/50] toplevel: Makefile.def: add install-strip dependency on
+ libsframe
+
+As noted in PR libsframe/30014 - FTBFS: install-strip fails because
+bfdlib relinks and fails to find libsframe, the install time
+dependencies of libbfd need to be updated.
+
+	PR libsframe/30014
+	* Makefile.def: Reflect that libsframe needs to installed before
+	libbfd.  Reorder a bit to better track libsframe dependencies.
+	* Makefile.in: Regenerate.
+
+(cherry picked from commit b8d21eb0cd10d6127e77cc437d82e949adb0c454)
+---
+ Makefile.def | 5 ++++-
+ Makefile.in  | 3 ++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/Makefile.def
++++ b/Makefile.def
+@@ -493,7 +493,6 @@ dependencies = { module=install-binutils
+ dependencies = { module=install-strip-binutils; on=install-strip-opcodes; };
+ 
+ // Likewise for ld, libctf, and bfd.
+-dependencies = { module=install-bfd; on=install-libsframe; };
+ dependencies = { module=install-libctf; on=install-bfd; };
+ dependencies = { module=install-ld; on=install-bfd; };
+ dependencies = { module=install-ld; on=install-libctf; };
+@@ -501,6 +500,10 @@ dependencies = { module=install-strip-li
+ dependencies = { module=install-strip-ld; on=install-strip-bfd; };
+ dependencies = { module=install-strip-ld; on=install-strip-libctf; };
+ 
++// libbfd depends on libsframe
++dependencies = { module=install-bfd; on=install-libsframe; };
++dependencies = { module=install-strip-bfd; on=install-strip-libsframe; };
++
+ // libopcodes depends on libbfd
+ dependencies = { module=configure-opcodes; on=configure-bfd; hard=true; };
+ dependencies = { module=install-opcodes; on=install-bfd; };
+--- a/Makefile.in
++++ b/Makefile.in
+@@ -64549,13 +64549,14 @@ all-stageautoprofile-binutils: maybe-all
+ all-stageautofeedback-binutils: maybe-all-stageautofeedback-libsframe
+ install-binutils: maybe-install-opcodes
+ install-strip-binutils: maybe-install-strip-opcodes
+-install-bfd: maybe-install-libsframe
+ install-libctf: maybe-install-bfd
+ install-ld: maybe-install-bfd
+ install-ld: maybe-install-libctf
+ install-strip-libctf: maybe-install-strip-bfd
+ install-strip-ld: maybe-install-strip-bfd
+ install-strip-ld: maybe-install-strip-libctf
++install-bfd: maybe-install-libsframe
++install-strip-bfd: maybe-install-strip-libsframe
+ configure-opcodes: configure-bfd
+ configure-stage1-opcodes: configure-stage1-bfd
+ configure-stage2-opcodes: configure-stage2-bfd
diff --git a/toolchain/binutils/patches/2.40/018-gprofng-PR29521-docs-man-pages-are-not-in-the-releas.patch b/toolchain/binutils/patches/2.40/018-gprofng-PR29521-docs-man-pages-are-not-in-the-releas.patch
new file mode 100644
index 0000000..ae55764
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/018-gprofng-PR29521-docs-man-pages-are-not-in-the-releas.patch
@@ -0,0 +1,703 @@
+From c6e269febbc946a54ed9dbbb2dc70feba6017607 Mon Sep 17 00:00:00 2001
+From: Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
+Date: Fri, 20 Jan 2023 15:39:55 -0800
+Subject: [PATCH 18/50] gprofng: PR29521 [docs] man pages are not in the
+ release tarball
+
+gprofng/ChangeLog
+2023-01-20  Vladimir Mezentsev  <vladimir.mezentsev@oracle.com>
+
+	PR gprofng/29521
+	* configure.ac: Check if $MAKEINFO and $HELP2MAN are missing.
+	* Makefile.am: Build doc if $MAKEINFO exists.
+	* doc/gprofng.texi: Update documentation for gprofng.
+	* doc/Makefile.am: Build gprofng.1.
+	* src/Makefile.am: Move the build of gprofng.1 to doc/Makefile.am.
+	* configure: Rebuild.
+	* Makefile.in: Rebuild.
+	* doc/Makefile.in: Rebuild.
+	* src/Makefile.in: Rebuild.
+---
+ gprofng/Makefile.am      |   2 +-
+ gprofng/Makefile.in      |   2 +-
+ gprofng/configure        |  79 +++++++++++++++---
+ gprofng/configure.ac     |  21 +++--
+ gprofng/doc/Makefile.am  |  24 +++++-
+ gprofng/doc/Makefile.in  |  93 ++++++++++++++++++---
+ gprofng/doc/gprofng.texi | 169 +++++++++++++++++++++++++++++++++++++++
+ gprofng/src/Makefile.am  |   8 +-
+ gprofng/src/Makefile.in  |   8 +-
+ 9 files changed, 364 insertions(+), 42 deletions(-)
+
+--- a/gprofng/Makefile.am
++++ b/gprofng/Makefile.am
+@@ -23,7 +23,7 @@ AUTOMAKE_OPTIONS = dejagnu foreign
+ if BUILD_COLLECTOR
+     COLLECTOR_SUBDIRS = libcollector
+ endif
+-if BUILD_MAN
++if BUILD_DOC
+     DOC_SUBDIR = doc
+ endif
+ if BUILD_SRC
+--- a/gprofng/Makefile.in
++++ b/gprofng/Makefile.in
+@@ -381,7 +381,7 @@ zlibinc = @zlibinc@
+ ACLOCAL_AMFLAGS = -I . -I .. 
+ AUTOMAKE_OPTIONS = dejagnu foreign
+ @BUILD_COLLECTOR_TRUE@COLLECTOR_SUBDIRS = libcollector
+-@BUILD_MAN_TRUE@DOC_SUBDIR = doc
++@BUILD_DOC_TRUE@DOC_SUBDIR = doc
+ @BUILD_SRC_TRUE@SRC_SUBDIRS = src gp-display-html $(DOC_SUBDIR)
+ SUBDIRS = $(COLLECTOR_SUBDIRS) $(SRC_SUBDIRS)
+ DIST_SUBDIRS = libcollector src gp-display-html $(DOC_SUBDIR)
+--- a/gprofng/configure
++++ b/gprofng/configure
+@@ -639,6 +639,8 @@ GPROFNG_CPPFLAGS
+ GPROFNG_NO_FORMAT_TRUNCATION_CFLAGS
+ GPROFNG_CFLAGS
+ LD_NO_AS_NEEDED
++BUILD_DOC_FALSE
++BUILD_DOC_TRUE
+ BUILD_MAN_FALSE
+ BUILD_MAN_TRUE
+ HELP2MAN
+@@ -12221,7 +12223,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 12224 "configure"
++#line 12226 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -12327,7 +12329,7 @@ else
+   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+   lt_status=$lt_dlunknown
+   cat > conftest.$ac_ext <<_LT_EOF
+-#line 12330 "configure"
++#line 12332 "configure"
+ #include "confdefs.h"
+ 
+ #if HAVE_DLFCN_H
+@@ -16737,9 +16739,58 @@ fi
+ 
+ # Generate manpages, if possible.
+ build_man=false
++build_doc=false
+ if test $cross_compiling = no; then
++  for ac_prog in help2man
++do
++  # Extract the first word of "$ac_prog", so it can be a program name with args.
++set dummy $ac_prog; ac_word=$2
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
++$as_echo_n "checking for $ac_word... " >&6; }
++if ${ac_cv_prog_HELP2MAN+:} false; then :
++  $as_echo_n "(cached) " >&6
++else
++  if test -n "$HELP2MAN"; then
++  ac_cv_prog_HELP2MAN="$HELP2MAN" # Let the user override the test.
++else
++as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH
++do
++  IFS=$as_save_IFS
++  test -z "$as_dir" && as_dir=.
++    for ac_exec_ext in '' $ac_executable_extensions; do
++  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
++    ac_cv_prog_HELP2MAN="$ac_prog"
++    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
++    break 2
++  fi
++done
++  done
++IFS=$as_save_IFS
++
++fi
++fi
++HELP2MAN=$ac_cv_prog_HELP2MAN
++if test -n "$HELP2MAN"; then
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $HELP2MAN" >&5
++$as_echo "$HELP2MAN" >&6; }
++else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
++$as_echo "no" >&6; }
++fi
+ 
+-HELP2MAN=${HELP2MAN-"${am_missing_run}help2man"}
++
++  test -n "$HELP2MAN" && break
++done
++test -n "$HELP2MAN" || HELP2MAN="$MISSING help2man"
++
++  case "x$HELP2MAN" in
++    x | */missing\ help2man* )
++      { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gprofng: help2man is missing. Man pages will not be built." >&5
++$as_echo "$as_me: WARNING: gprofng: help2man is missing. Man pages will not be built." >&2;}
++      ;;
++    * ) build_man=true ;;
++    esac
+ 
+   for ac_prog in makeinfo
+ do
+@@ -16782,10 +16833,10 @@ fi
+ 
+   test -n "$MAKEINFO" && break
+ done
+-test -n "$MAKEINFO" || MAKEINFO=""@echo makeinfo missing; true""
++test -n "$MAKEINFO" || MAKEINFO="$MISSING makeinfo"
+ 
+-  case "$MAKEINFO" in
+-    *true)
++  case "x$MAKEINFO" in
++    x | */missing\ makeinfo*)
+       { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: gprofng: makeinfo is missing. Info documentation will not be built." >&5
+ $as_echo "$as_me: WARNING: gprofng: makeinfo is missing. Info documentation will not be built." >&2;}
+       ;;
+@@ -16796,9 +16847,7 @@ $as_echo "$as_me: WARNING: gprofng: make
+ $as_echo "$as_me: WARNING: gprofng: $MAKEINFO is too old. Info documentation will not be built." >&2;}
+ 	  MAKEINFO="@echo $MAKEINFO is too old, 6.5 or newer required; true"
+ 	  ;;
+-	x* )
+-	  build_man=true
+-	  ;;
++	x* ) build_doc=true ;;
+ 	esac
+       ;;
+     esac
+@@ -16812,6 +16861,14 @@ else
+   BUILD_MAN_FALSE=
+ fi
+ 
++ if test x$build_doc = xtrue; then
++  BUILD_DOC_TRUE=
++  BUILD_DOC_FALSE='#'
++else
++  BUILD_DOC_TRUE='#'
++  BUILD_DOC_FALSE=
++fi
++
+ 
+ LD_NO_AS_NEEDED=${no_as_needed}
+ 
+@@ -17070,6 +17127,10 @@ if test -z "${BUILD_MAN_TRUE}" && test -
+   as_fn_error $? "conditional \"BUILD_MAN\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
++if test -z "${BUILD_DOC_TRUE}" && test -z "${BUILD_DOC_FALSE}"; then
++  as_fn_error $? "conditional \"BUILD_DOC\" was never defined.
++Usually this means the macro was only invoked conditionally." "$LINENO" 5
++fi
+ 
+ : "${CONFIG_STATUS=./config.status}"
+ ac_write_fail=0
+--- a/gprofng/configure.ac
++++ b/gprofng/configure.ac
+@@ -210,11 +210,19 @@ AM_ZLIB
+ 
+ # Generate manpages, if possible.
+ build_man=false
++build_doc=false
+ if test $cross_compiling = no; then
+-  AM_MISSING_PROG(HELP2MAN, help2man)
+-  AC_CHECK_PROGS([MAKEINFO], makeinfo, ["@echo makeinfo missing; true"])
+-  case "$MAKEINFO" in
+-    *true)
++  AC_CHECK_PROGS([HELP2MAN], help2man, [$MISSING help2man])
++  case "x$HELP2MAN" in
++    x | */missing\ help2man* )
++      AC_MSG_WARN([gprofng: help2man is missing. Man pages will not be built.])
++      ;;
++    * ) build_man=true ;;
++    esac
++
++  AC_CHECK_PROGS([MAKEINFO], makeinfo, [$MISSING makeinfo])
++  case "x$MAKEINFO" in
++    x | */missing\ makeinfo*)
+       AC_MSG_WARN([gprofng: makeinfo is missing. Info documentation will not be built.])
+       ;;
+     *)
+@@ -223,15 +231,14 @@ if test $cross_compiling = no; then
+ 	  AC_MSG_WARN([gprofng: $MAKEINFO is too old. Info documentation will not be built.])
+ 	  MAKEINFO="@echo $MAKEINFO is too old, 6.5 or newer required; true"
+ 	  ;;
+-	x* )
+-	  build_man=true
+-	  ;;
++	x* ) build_doc=true ;;
+ 	esac
+       ;;
+     esac
+   AC_SUBST(MAKEINFO)
+ fi
+ AM_CONDITIONAL([BUILD_MAN], [test x$build_man = xtrue])
++AM_CONDITIONAL([BUILD_DOC], [test x$build_doc = xtrue])
+ 
+ AC_SUBST(LD_NO_AS_NEEDED, [${no_as_needed}])
+ AC_SUBST(GPROFNG_CFLAGS, [${gprofng_cflags}])
+--- a/gprofng/doc/Makefile.am
++++ b/gprofng/doc/Makefile.am
+@@ -19,9 +19,31 @@
+ 
+ AUTOMAKE_OPTIONS = info-in-builddir foreign no-texinfo.tex
+ 
++# Options to extract the man page
++MANCONF = -Dman
++
++TEXI2POD = perl $(srcdir)/../../etc/texi2pod.pl $(AM_MAKEINFOFLAGS)
++POD2MAN = pod2man --center="User Commands" \
++	--release="binutils-$(VERSION)" --section=1
++
+ info_TEXINFOS       = gprofng.texi
+ gprofng_TEXINFOS    = fdl.texi
+ TEXINFO_TEX         = .
+ MAKEINFOHTML        = $(MAKEINFO) --html --no-split
+ 
+-MAINTAINERCLEANFILES = gprofng.info
++man_MANS = gprofng.1
++
++# Build the man page from the texinfo file
++# The sed command removes the no-adjust Nroff command so that
++# the man output looks standard.
++gprofng.1: $(srcdir)/gprofng.texi
++	$(AM_V_GEN)touch $@
++	$(AM_V_at)-$(TEXI2POD) $(MANCONF) < $(srcdir)/gprofng.texi > gprofng.pod
++	$(AM_V_at)-($(POD2MAN) gprofng.pod | \
++	  sed -e '/^.if n .na/d' > $@.tmp && \
++	  mv -f $@.tmp $@) || (rm -f $@.tmp && exit 1)
++	$(AM_V_at)rm -f gprofng.pod
++
++MAINTAINERCLEANFILES = gprofng.info $(man_MANS)
++
++info: $(man_MANS)
+--- a/gprofng/doc/Makefile.in
++++ b/gprofng/doc/Makefile.in
+@@ -182,7 +182,7 @@ am__can_run_installinfo = \
+     n|no|NO) false;; \
+     *) (install-info --version) >/dev/null 2>&1;; \
+   esac
+-am__installdirs = "$(DESTDIR)$(infodir)"
++am__installdirs = "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"
+ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+ am__vpath_adj = case $$p in \
+     $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+@@ -210,6 +210,9 @@ am__uninstall_files_from_dir = { \
+     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+          $(am__cd) "$$dir" && rm -f $$files; }; \
+   }
++man1dir = $(mandir)/man1
++NROFF = nroff
++MANS = $(man_MANS)
+ am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+ am__DIST_COMMON = $(gprofng_TEXINFOS) $(srcdir)/Makefile.in \
+ 	$(top_srcdir)/../mkinstalldirs mdate-sh texinfo.tex
+@@ -361,11 +364,19 @@ top_srcdir = @top_srcdir@
+ zlibdir = @zlibdir@
+ zlibinc = @zlibinc@
+ AUTOMAKE_OPTIONS = info-in-builddir foreign no-texinfo.tex
++
++# Options to extract the man page
++MANCONF = -Dman
++TEXI2POD = perl $(srcdir)/../../etc/texi2pod.pl $(AM_MAKEINFOFLAGS)
++POD2MAN = pod2man --center="User Commands" \
++	--release="binutils-$(VERSION)" --section=1
++
+ info_TEXINFOS = gprofng.texi
+ gprofng_TEXINFOS = fdl.texi
+ TEXINFO_TEX = .
+ MAKEINFOHTML = $(MAKEINFO) --html --no-split
+-MAINTAINERCLEANFILES = gprofng.info
++man_MANS = gprofng.1
++MAINTAINERCLEANFILES = gprofng.info $(man_MANS)
+ all: all-am
+ 
+ .SUFFIXES:
+@@ -558,6 +569,49 @@ maintainer-clean-aminfo:
+ 	  echo " rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]"; \
+ 	  rm -f $$i $$i-[0-9] $$i-[0-9][0-9] $$i_i[0-9] $$i_i[0-9][0-9]; \
+ 	done
++install-man1: $(man_MANS)
++	@$(NORMAL_INSTALL)
++	@list1=''; \
++	list2='$(man_MANS)'; \
++	test -n "$(man1dir)" \
++	  && test -n "`echo $$list1$$list2`" \
++	  || exit 0; \
++	echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \
++	$(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \
++	{ for i in $$list1; do echo "$$i"; done;  \
++	if test -n "$$list2"; then \
++	  for i in $$list2; do echo "$$i"; done \
++	    | sed -n '/\.1[a-z]*$$/p'; \
++	fi; \
++	} | while read p; do \
++	  if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
++	  echo "$$d$$p"; echo "$$p"; \
++	done | \
++	sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
++	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \
++	sed 'N;N;s,\n, ,g' | { \
++	list=; while read file base inst; do \
++	  if test "$$base" = "$$inst"; then list="$$list $$file"; else \
++	    echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \
++	    $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \
++	  fi; \
++	done; \
++	for i in $$list; do echo "$$i"; done | $(am__base_list) | \
++	while read files; do \
++	  test -z "$$files" || { \
++	    echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \
++	    $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \
++	done; }
++
++uninstall-man1:
++	@$(NORMAL_UNINSTALL)
++	@list=''; test -n "$(man1dir)" || exit 0; \
++	files=`{ for i in $$list; do echo "$$i"; done; \
++	l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \
++	  sed -n '/\.1[a-z]*$$/p'; \
++	} | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \
++	      -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \
++	dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir)
+ tags TAGS:
+ 
+ ctags CTAGS:
+@@ -600,9 +654,9 @@ distdir: $(DISTFILES)
+ 	  dist-info
+ check-am: all-am
+ check: check-am
+-all-am: Makefile $(INFO_DEPS)
++all-am: Makefile $(INFO_DEPS) $(MANS)
+ installdirs:
+-	for dir in "$(DESTDIR)$(infodir)"; do \
++	for dir in "$(DESTDIR)$(infodir)" "$(DESTDIR)$(man1dir)"; do \
+ 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ 	done
+ install: install-am
+@@ -652,11 +706,9 @@ html: html-am
+ 
+ html-am: $(HTMLS)
+ 
+-info: info-am
+-
+ info-am: $(INFO_DEPS)
+ 
+-install-data-am: install-info-am
++install-data-am: install-info-am install-man
+ 
+ install-dvi: install-dvi-am
+ 
+@@ -739,7 +791,7 @@ install-info-am: $(INFO_DEPS)
+ 	    install-info --info-dir="$(DESTDIR)$(infodir)" "$(DESTDIR)$(infodir)/$$relfile" || :;\
+ 	  done; \
+ 	else : ; fi
+-install-man:
++install-man: install-man1
+ 
+ install-pdf: install-pdf-am
+ 
+@@ -794,7 +846,9 @@ ps: ps-am
+ ps-am: $(PSS)
+ 
+ uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
+-	uninstall-pdf-am uninstall-ps-am
++	uninstall-man uninstall-pdf-am uninstall-ps-am
++
++uninstall-man: uninstall-man1
+ 
+ .MAKE: install-am install-strip
+ 
+@@ -804,19 +858,32 @@ uninstall-am: uninstall-dvi-am uninstall
+ 	html-am info info-am install install-am install-data \
+ 	install-data-am install-dvi install-dvi-am install-exec \
+ 	install-exec-am install-html install-html-am install-info \
+-	install-info-am install-man install-pdf install-pdf-am \
+-	install-ps install-ps-am install-strip installcheck \
+-	installcheck-am installdirs maintainer-clean \
++	install-info-am install-man install-man1 install-pdf \
++	install-pdf-am install-ps install-ps-am install-strip \
++	installcheck installcheck-am installdirs maintainer-clean \
+ 	maintainer-clean-aminfo maintainer-clean-generic \
+ 	maintainer-clean-vti mostlyclean mostlyclean-aminfo \
+ 	mostlyclean-generic mostlyclean-libtool mostlyclean-vti pdf \
+ 	pdf-am ps ps-am tags-am uninstall uninstall-am \
+ 	uninstall-dvi-am uninstall-html-am uninstall-info-am \
+-	uninstall-pdf-am uninstall-ps-am
++	uninstall-man uninstall-man1 uninstall-pdf-am uninstall-ps-am
+ 
+ .PRECIOUS: Makefile
+ 
+ 
++# Build the man page from the texinfo file
++# The sed command removes the no-adjust Nroff command so that
++# the man output looks standard.
++gprofng.1: $(srcdir)/gprofng.texi
++	$(AM_V_GEN)touch $@
++	$(AM_V_at)-$(TEXI2POD) $(MANCONF) < $(srcdir)/gprofng.texi > gprofng.pod
++	$(AM_V_at)-($(POD2MAN) gprofng.pod | \
++	  sed -e '/^.if n .na/d' > $@.tmp && \
++	  mv -f $@.tmp $@) || (rm -f $@.tmp && exit 1)
++	$(AM_V_at)rm -f gprofng.pod
++
++info: $(man_MANS)
++
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
+--- a/gprofng/doc/gprofng.texi
++++ b/gprofng/doc/gprofng.texi
+@@ -1,5 +1,8 @@
+ \input texinfo @c -*-texinfo-*-
+ 
++@c for $sect (qw(NAME SYNOPSIS TARGET DESCRIPTION OPTIONS ENVIRONMENT FILES
++@c               BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
++
+ @c ----------------------------------------------------------------------------
+ @c This is the Texinfo source file for the GPROFNG manual.
+ @c
+@@ -59,6 +62,10 @@ gprofng
+ @cindex \label\, \string\
+ @end macro
+ 
++@macro gcctabopt{body}
++@code{\body\}
++@end macro
++
+ @c -- Get the version information ---------------------------------------------
+ @include version.texi
+ 
+@@ -99,6 +106,20 @@ section entitled ``GNU Free Documentatio
+ @page
+ @vskip 0pt plus 1filll
+ @insertcopying
++
++@c man begin COPYRIGHT
++
++Copyright @copyright{} 2022-2023 Free Software Foundation, Inc.
++
++Permission is granted to copy, distribute and/or modify this document
++under the terms of the GNU Free Documentation License, Version 1.3
++or any later version published by the Free Software Foundation;
++with no Invariant Sections, with no Front-Cover Texts, and with no
++Back-Cover Texts.  A copy of the license is included in the
++section entitled ``GNU Free Documentation License''.
++
++@c man end
++
+ @end titlepage
+ 
+ @c -- Generate the Table of Contents ------------------------------------------
+@@ -163,6 +184,154 @@ Terminology
+ @end menu
+ @end ifinfo
+ 
++@ifset man
++
++@c man title gprofng the driver for the gprofng tool suite
++
++@c man begin SYNOPSIS
++gprofng [OPTION(S)] ACTION [@b{QUALIFIER}] [ARGUMENTS] TARGET
++@c man end
++
++@c man begin DESCRIPTION
++This is the driver for the GPROFNG tools suite to gather and analyze performance data.
++
++The driver executes the action specified. An example of an action is @code{collect}
++to collect performance data. Depending on the action, a qualifier may be needed to
++define the command. Several qualifiers support options. The last item on the command
++is the target the command applies to.
++
++For example, to collect performance data for an application called @code{a.out} and
++store the results in experiment directory @code{mydata.er}, the following command may
++be used:
++
++@smallexample
++$ gprofng collect app -o mydata.er a.out
++@end smallexample
++
++In this example, the action is @code{collect}, the qualifier is @code{app}, the single
++argument is @code{-o mydata.er} and the target is @code{a.out}.
++
++If gprofng is executed without any additional option, action, or target, a usage
++overview is printed.
++
++@c man end
++
++@c man begin OPTIONS
++
++@table @gcctabopt
++
++@item @var{--version}
++print the version number and exit.
++
++@item @var{--help}
++print usage information and exit.
++
++@end table
++
++@c man end
++
++@c man begin NOTES
++
++The gprofng driver supports the following commands.
++
++@c The man pages for the commands below can be viewed using the command name with "gprofng" replaced by "gp" and the spaces replaced by a dash ("-"). For example the man page
++@c        name for "gprofng collect app" is "gp-collect-app".
++
++Collect performance data:
++
++@table @code
++
++@item gprofng collect app
++collect application performance data.
++
++@end table
++
++Display the performance results:
++
++@table @code
++
++@item gprofng display text
++display the performance data in ASCII format.
++
++@item gprofng display html
++generate an HTML file from one or more experiments.
++
++@end table
++
++Miscellaneous commands:
++
++@table @code
++
++@item gprofng display src
++display source or disassembly with compiler annotations.
++
++@item gprofng archive
++include binaries and source code in an experiment directory.
++
++@end table
++
++It is also possible to invoke the lower level commands directly, but since
++these are subject to change, in particular the options, we recommend to
++use the driver.
++
++@c man end
++
++@c man begin ENVIRONMENT
++The following environment variables are supported:
++
++@table @code
++
++@item @env{GPROFNG_MAX_CALL_STACK_DEPTH}
++set the depth of the call stack (default is 256).
++
++@item @env{GPROFNG_USE_JAVA_OPTIONS}
++may be set when profiling a C/C++ application that uses dlopen() to execute Java code.
++
++@item @env{GPROFNG_SSH_REMOTE_DISPLAY}
++use this variable to define the ssh command executed by the remote display tool.
++
++@item @env{GPROFNG_SKIP_VALIDATION}
++set this variable to disable checking hardware, system, and Java versions.
++
++@item @env{GPROFNG_ALLOW_CORE_DUMP}
++set this variable to allow a core file to be generated; otherwise an error report is created on /tmp.
++
++@item @env{GPROFNG_ARCHIVE}
++use this variable to define the settings for automatic archiving upon experiment recording completion.
++
++@item @env{GPROFNG_ARCHIVE_COMMON_DIR}
++set this variable to the location of the common archive.
++
++@item @env{GPROFNG_JAVA_MAX_CALL_STACK_DEPTH}
++set the depth of the Java call stack; the default is 256; set to 0 to disable capturing of call stacks.
++
++@item @env{GPROFNG_JAVA_NATIVE_MAX_CALL_STACK_DEPTH}
++set the depth of the Java native call stack; the default is 256; set to 0 to disable capturing of call stacks (JNI and assembly call stacks are not captured).
++
++@end table
++
++@c man end
++
++@c man begin SEEALSO
++The man pages for the various gprofng commands are not available yet, but
++the @option{--help} option supported on each of the commands lists the options
++and provides more information.
++
++For example this displays the options supported on the @command{gprofng collect app}
++command:
++
++@smallexample
++$ gprofng collect app --help
++@end smallexample
++
++The user guide is available as an Info entry for @file{gprofng}.
++@c man end
++
++@end ifset
++
++@c man begin DESCRIPTION
++@c man end
++
+ @c -- A new node --------------------------------------------------------------
+ @node    Introduction
+ @chapter Introduction
+--- a/gprofng/src/Makefile.am
++++ b/gprofng/src/Makefile.am
+@@ -160,7 +160,7 @@ gp_display_text_LDADD = $(LIBGPROFNG) $(
+ 
+ if BUILD_MAN
+ 
+-man_MANS = gprofng.1 \
++man_MANS = \
+ 	gp-archive.1 \
+ 	gp-collect-app.1 \
+ 	gp-display-src.1 \
+@@ -191,10 +191,6 @@ H2M_FILTER = | sed 's/\.TP/\.TP\n.B/' |
+   | sed 's/See also:/\.SH SEE ALSO/' | sed 's/Documentation:/.SH DOCUMENTATION/' \
+   | sed 's/Limitations:/.SH LIMITATIONS/'
+ 
+-gprofng.1: $(srcdir)/gprofng.cc $(common_mandeps) | ./gprofng$(EXEEXT)
+-	$(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
+-	  --name=$(TEXT_GPROFNG) ./gprofng$(EXEEXT) $(H2M_FILTER) > $@
+-
+ gp-archive.1: $(srcdir)/gp-archive.cc $(common_mandeps) | ./gp-archive$(EXEEXT)
+ 	$(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
+ 	  --name=$(TEXT_GP_ARCHIVE) ./gp-archive$(EXEEXT) $(H2M_FILTER) > $@
+@@ -223,3 +219,5 @@ dist-hook: $(LIBGPROFNG)
+ 
+ install-data-local: install-pkglibLTLIBRARIES
+ 	rm -f $(DESTDIR)/$(pkglibdir)/*.la $(DESTDIR)/$(pkglibdir)/*.a
++
++$(srcdir)/DbeSession.cc: QLParser.tab.hh
+--- a/gprofng/src/Makefile.in
++++ b/gprofng/src/Makefile.in
+@@ -572,7 +572,7 @@ gp_display_src_SOURCES = gp-display-src.
+ gp_display_src_LDADD = $(LIBGPROFNG) $(CLOCK_GETTIME_LINK) $(ZLIB)
+ gp_display_text_SOURCES = gp-display-text.cc ipc.cc ipcio.cc
+ gp_display_text_LDADD = $(LIBGPROFNG) $(CLOCK_GETTIME_LINK) $(ZLIB)
+-@BUILD_MAN_TRUE@man_MANS = gprofng.1 \
++@BUILD_MAN_TRUE@man_MANS = \
+ @BUILD_MAN_TRUE@	gp-archive.1 \
+ @BUILD_MAN_TRUE@	gp-collect-app.1 \
+ @BUILD_MAN_TRUE@	gp-display-src.1 \
+@@ -1176,10 +1176,6 @@ uninstall-man: uninstall-man1
+ QLParser.tab.cc QLParser.tab.hh: QLParser.yy
+ 	$(BISON) $^
+ 
+-@BUILD_MAN_TRUE@gprofng.1: $(srcdir)/gprofng.cc $(common_mandeps) | ./gprofng$(EXEEXT)
+-@BUILD_MAN_TRUE@	$(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
+-@BUILD_MAN_TRUE@	  --name=$(TEXT_GPROFNG) ./gprofng$(EXEEXT) $(H2M_FILTER) > $@
+-
+ @BUILD_MAN_TRUE@gp-archive.1: $(srcdir)/gp-archive.cc $(common_mandeps) | ./gp-archive$(EXEEXT)
+ @BUILD_MAN_TRUE@	$(AM_V_GEN)_BUILDING_MANPAGE=1 $(HELP2MAN) $(HELP2MAN_OPT) \
+ @BUILD_MAN_TRUE@	  --name=$(TEXT_GP_ARCHIVE) ./gp-archive$(EXEEXT) $(H2M_FILTER) > $@
+@@ -1207,6 +1203,8 @@ dist-hook: $(LIBGPROFNG)
+ install-data-local: install-pkglibLTLIBRARIES
+ 	rm -f $(DESTDIR)/$(pkglibdir)/*.la $(DESTDIR)/$(pkglibdir)/*.a
+ 
++$(srcdir)/DbeSession.cc: QLParser.tab.hh
++
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
+ # Otherwise a system limit (for SysV at least) may be exceeded.
+ .NOEXPORT:
diff --git a/toolchain/binutils/patches/2.40/020-gprofng-PR30043-libgprofng.so.-are-installed-to-a-wr.patch b/toolchain/binutils/patches/2.40/020-gprofng-PR30043-libgprofng.so.-are-installed-to-a-wr.patch
new file mode 100644
index 0000000..d8d76a2
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/020-gprofng-PR30043-libgprofng.so.-are-installed-to-a-wr.patch
@@ -0,0 +1,212 @@
+From edd36b26f3506eeb259534ba2493e15c728cd280 Mon Sep 17 00:00:00 2001
+From: Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
+Date: Wed, 25 Jan 2023 19:21:38 -0800
+Subject: [PATCH 20/50] gprofng: PR30043 libgprofng.so.* are installed to a
+ wrong location
+
+gprofng/ChangeLog
+2023-01-25  Vladimir Mezentsev  <vladimir.mezentsev@oracle.com>
+
+	PR gprofng/30043
+	PR gprofng/28972
+	* src/Makefile.am: Use lib_LTLIBRARIES instead of pkglib_LTLIBRARIES.
+	* src/Makefile.in: Rebuild.
+---
+ gprofng/src/Makefile.am |  7 +---
+ gprofng/src/Makefile.in | 76 +++++++++++++++++++----------------------
+ 2 files changed, 37 insertions(+), 46 deletions(-)
+
+--- a/gprofng/src/Makefile.am
++++ b/gprofng/src/Makefile.am
+@@ -124,7 +124,7 @@ BUILT_SOURCES = QLParser.tab.hh
+ EXTRA_DIST = QLParser.yy $(man_MANS)
+ 
+ 
+-pkglib_LTLIBRARIES = $(LIBGPROFNG)
++lib_LTLIBRARIES = $(LIBGPROFNG)
+ libgprofng_la_SOURCES = $(CCSOURCES) $(CSOURCES)
+ libgprofng_la_LDFLAGS = -version-info 0:0:0
+ 
+@@ -215,9 +215,4 @@ endif
+ # so ensure that the necessary libraries are built at dist time.
+ dist-hook: $(LIBGPROFNG)
+ 
+-.PHONY: install-data-local
+-
+-install-data-local: install-pkglibLTLIBRARIES
+-	rm -f $(DESTDIR)/$(pkglibdir)/*.la $(DESTDIR)/$(pkglibdir)/*.a
+-
+ $(srcdir)/DbeSession.cc: QLParser.tab.hh
+--- a/gprofng/src/Makefile.in
++++ b/gprofng/src/Makefile.in
+@@ -155,9 +155,9 @@ am__uninstall_files_from_dir = { \
+     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+          $(am__cd) "$$dir" && rm -f $$files; }; \
+   }
+-am__installdirs = "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(bindir)" \
++am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
+ 	"$(DESTDIR)$(man1dir)" "$(DESTDIR)$(dbedir)"
+-LTLIBRARIES = $(pkglib_LTLIBRARIES)
++LTLIBRARIES = $(lib_LTLIBRARIES)
+ am__DEPENDENCIES_1 =
+ libgprofng_la_DEPENDENCIES = $(top_builddir)/../opcodes/libopcodes.la \
+ 	$(top_builddir)/../bfd/libbfd.la $(am__DEPENDENCIES_1)
+@@ -548,7 +548,7 @@ AM_CFLAGS = $(GPROFNG_CFLAGS) $(PTHREAD_
+ AM_CXXFLAGS = $(AM_CFLAGS)
+ BUILT_SOURCES = QLParser.tab.hh
+ EXTRA_DIST = QLParser.yy $(man_MANS)
+-pkglib_LTLIBRARIES = $(LIBGPROFNG)
++lib_LTLIBRARIES = $(LIBGPROFNG)
+ libgprofng_la_SOURCES = $(CCSOURCES) $(CSOURCES)
+ libgprofng_la_LDFLAGS = -version-info 0:0:0
+ 
+@@ -636,33 +636,33 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(
+ 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+ $(am__aclocal_m4_deps):
+ 
+-install-pkglibLTLIBRARIES: $(pkglib_LTLIBRARIES)
++install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ 	@$(NORMAL_INSTALL)
+-	@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
++	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ 	list2=; for p in $$list; do \
+ 	  if test -f $$p; then \
+ 	    list2="$$list2 $$p"; \
+ 	  else :; fi; \
+ 	done; \
+ 	test -z "$$list2" || { \
+-	  echo " $(MKDIR_P) '$(DESTDIR)$(pkglibdir)'"; \
+-	  $(MKDIR_P) "$(DESTDIR)$(pkglibdir)" || exit 1; \
+-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkglibdir)'"; \
+-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkglibdir)"; \
++	  echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
++	  $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ 	}
+ 
+-uninstall-pkglibLTLIBRARIES:
++uninstall-libLTLIBRARIES:
+ 	@$(NORMAL_UNINSTALL)
+-	@list='$(pkglib_LTLIBRARIES)'; test -n "$(pkglibdir)" || list=; \
++	@list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ 	for p in $$list; do \
+ 	  $(am__strip_dir) \
+-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkglibdir)/$$f'"; \
+-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkglibdir)/$$f"; \
++	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
++	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ 	done
+ 
+-clean-pkglibLTLIBRARIES:
+-	-test -z "$(pkglib_LTLIBRARIES)" || rm -f $(pkglib_LTLIBRARIES)
+-	@list='$(pkglib_LTLIBRARIES)'; \
++clean-libLTLIBRARIES:
++	-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
++	@list='$(lib_LTLIBRARIES)'; \
+ 	locs=`for p in $$list; do echo $$p; done | \
+ 	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ 	      sort -u`; \
+@@ -672,7 +672,7 @@ clean-pkglibLTLIBRARIES:
+ 	}
+ 
+ libgprofng.la: $(libgprofng_la_OBJECTS) $(libgprofng_la_DEPENDENCIES) $(EXTRA_libgprofng_la_DEPENDENCIES) 
+-	$(AM_V_CXXLD)$(libgprofng_la_LINK) -rpath $(pkglibdir) $(libgprofng_la_OBJECTS) $(libgprofng_la_LIBADD) $(LIBS)
++	$(AM_V_CXXLD)$(libgprofng_la_LINK) -rpath $(libdir) $(libgprofng_la_OBJECTS) $(libgprofng_la_LIBADD) $(LIBS)
+ install-binPROGRAMS: $(bin_PROGRAMS)
+ 	@$(NORMAL_INSTALL)
+ 	@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+@@ -1039,8 +1039,10 @@ check-am: all-am
+ check: $(BUILT_SOURCES)
+ 	$(MAKE) $(AM_MAKEFLAGS) check-am
+ all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(DATA)
++install-binPROGRAMS: install-libLTLIBRARIES
++
+ installdirs:
+-	for dir in "$(DESTDIR)$(pkglibdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(dbedir)"; do \
++	for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(dbedir)"; do \
+ 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ 	done
+ install: $(BUILT_SOURCES)
+@@ -1078,8 +1080,8 @@ maintainer-clean-generic:
+ 	-test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+ clean: clean-am
+ 
+-clean-am: clean-binPROGRAMS clean-generic clean-libtool \
+-	clean-pkglibLTLIBRARIES mostlyclean-am
++clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
++	clean-libtool mostlyclean-am
+ 
+ distclean: distclean-am
+ 	-rm -rf ./$(DEPDIR)
+@@ -1099,13 +1101,13 @@ info: info-am
+ 
+ info-am:
+ 
+-install-data-am: install-data-local install-dbeDATA install-man
++install-data-am: install-dbeDATA install-man
+ 
+ install-dvi: install-dvi-am
+ 
+ install-dvi-am:
+ 
+-install-exec-am: install-binPROGRAMS install-pkglibLTLIBRARIES
++install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
+ 
+ install-html: install-html-am
+ 
+@@ -1145,30 +1147,29 @@ ps: ps-am
+ 
+ ps-am:
+ 
+-uninstall-am: uninstall-binPROGRAMS uninstall-dbeDATA uninstall-man \
+-	uninstall-pkglibLTLIBRARIES
++uninstall-am: uninstall-binPROGRAMS uninstall-dbeDATA \
++	uninstall-libLTLIBRARIES uninstall-man
+ 
+ uninstall-man: uninstall-man1
+ 
+ .MAKE: all check install install-am install-strip
+ 
+ .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean \
+-	clean-binPROGRAMS clean-generic clean-libtool \
+-	clean-pkglibLTLIBRARIES cscopelist-am ctags ctags-am dist-hook \
+-	distclean distclean-compile distclean-generic \
+-	distclean-libtool distclean-tags distdir dvi dvi-am html \
+-	html-am info info-am install install-am install-binPROGRAMS \
+-	install-data install-data-am install-data-local \
+-	install-dbeDATA install-dvi install-dvi-am install-exec \
+-	install-exec-am install-html install-html-am install-info \
+-	install-info-am install-man install-man1 install-pdf \
+-	install-pdf-am install-pkglibLTLIBRARIES install-ps \
++	clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
++	clean-libtool cscopelist-am ctags ctags-am dist-hook distclean \
++	distclean-compile distclean-generic distclean-libtool \
++	distclean-tags distdir dvi dvi-am html html-am info info-am \
++	install install-am install-binPROGRAMS install-data \
++	install-data-am install-dbeDATA install-dvi install-dvi-am \
++	install-exec install-exec-am install-html install-html-am \
++	install-info install-info-am install-libLTLIBRARIES \
++	install-man install-man1 install-pdf install-pdf-am install-ps \
+ 	install-ps-am install-strip installcheck installcheck-am \
+ 	installdirs maintainer-clean maintainer-clean-generic \
+ 	mostlyclean mostlyclean-compile mostlyclean-generic \
+ 	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ 	uninstall-am uninstall-binPROGRAMS uninstall-dbeDATA \
+-	uninstall-man uninstall-man1 uninstall-pkglibLTLIBRARIES
++	uninstall-libLTLIBRARIES uninstall-man uninstall-man1
+ 
+ .PRECIOUS: Makefile
+ 
+@@ -1198,11 +1199,6 @@ QLParser.tab.cc QLParser.tab.hh: QLParse
+ # so ensure that the necessary libraries are built at dist time.
+ dist-hook: $(LIBGPROFNG)
+ 
+-.PHONY: install-data-local
+-
+-install-data-local: install-pkglibLTLIBRARIES
+-	rm -f $(DESTDIR)/$(pkglibdir)/*.la $(DESTDIR)/$(pkglibdir)/*.a
+-
+ $(srcdir)/DbeSession.cc: QLParser.tab.hh
+ 
+ # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/toolchain/binutils/patches/2.40/026-RISC-V-make-C-extension-JAL-available-again-for-32-b.patch b/toolchain/binutils/patches/2.40/026-RISC-V-make-C-extension-JAL-available-again-for-32-b.patch
new file mode 100644
index 0000000..4129a22
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/026-RISC-V-make-C-extension-JAL-available-again-for-32-b.patch
@@ -0,0 +1,115 @@
+From 27f59ec47a18277b6ea3548f405263ef558f5217 Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Tue, 31 Jan 2023 09:47:22 +0100
+Subject: [PATCH 26/50] RISC-V: make C-extension JAL available again for
+ (32-bit) assembly
+
+Along with the normal JAL alias, the C-extension one should have been
+moved as well by 839189bc932e ("RISC-V: re-arrange opcode table for
+consistent alias handling"), for the assembler to actually be able to
+use it where/when possible.
+
+Since neither this nor any other compressed branch insn was being tested
+so far, take the opportunity and introduce a new testcase covering those.
+---
+ gas/config/tc-riscv.c                 |  3 +++
+ gas/testsuite/gas/riscv/c-branch-na.d | 20 ++++++++++++++++++++
+ gas/testsuite/gas/riscv/c-branch.d    | 19 +++++++++++++++++++
+ gas/testsuite/gas/riscv/c-branch.s    | 11 +++++++++++
+ opcodes/riscv-opc.c                   |  2 +-
+ 5 files changed, 54 insertions(+), 1 deletion(-)
+ create mode 100644 gas/testsuite/gas/riscv/c-branch-na.d
+ create mode 100644 gas/testsuite/gas/riscv/c-branch.d
+ create mode 100644 gas/testsuite/gas/riscv/c-branch.s
+
+--- a/gas/config/tc-riscv.c
++++ b/gas/config/tc-riscv.c
+@@ -2762,6 +2762,8 @@ riscv_ip (char *str, struct riscv_cl_ins
+ 		case 'p':
+ 		  goto branch;
+ 		case 'a':
++		  if (oparg == insn->args + 1)
++		    goto jump_check_gpr;
+ 		  goto jump;
+ 		case 'S': /* Floating-point RS1 x8-x15.  */
+ 		  if (!reg_lookup (&asarg, RCLASS_FPR, &regno)
+@@ -3271,6 +3273,7 @@ riscv_ip (char *str, struct riscv_cl_ins
+ 		 but the 2nd (with 2 operands) might.  */
+ 	      if (oparg == insn->args)
+ 		{
++	    jump_check_gpr:
+ 		  asargStart = asarg;
+ 		  if (reg_lookup (&asarg, RCLASS_GPR, NULL)
+ 		      && (*asarg == ',' || (ISSPACE (*asarg) && asarg[1] == ',')))
+--- /dev/null
++++ b/gas/testsuite/gas/riscv/c-branch-na.d
+@@ -0,0 +1,20 @@
++#as: -march=rv32ic
++#source: c-branch.s
++#objdump: -drw -Mno-aliases
++
++.*:[ 	]+file format .*
++
++
++Disassembly of section .text:
++
++0+ <target>:
++[ 	]+[0-9a-f]+:[ 	]+c001[ 	]+c\.beqz[ 	]+s0,0 <target>[ 	]+0: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+dcfd[ 	]+c\.beqz[ 	]+s1,0 <target>[ 	]+2: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+fc75[ 	]+c\.bnez[ 	]+s0,0 <target>[ 	]+4: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+fced[ 	]+c\.bnez[ 	]+s1,0 <target>[ 	]+6: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+bfe5[ 	]+c\.j[ 	]+0 <target>[ 	]+8: R_RISCV_RVC_JUMP	.*
++[ 	]+[0-9a-f]+:[ 	]+3fdd[ 	]+c\.jal[ 	]+0 <target>[ 	]+a: R_RISCV_RVC_JUMP	.*
++[ 	]+[0-9a-f]+:[ 	]+9302[ 	]+c\.jalr[ 	]+t1
++[ 	]+[0-9a-f]+:[ 	]+8382[ 	]+c\.jr[ 	]+t2
++[ 	]+[0-9a-f]+:[ 	]+8082[ 	]+c\.jr[ 	]+ra
++#...
+--- /dev/null
++++ b/gas/testsuite/gas/riscv/c-branch.d
+@@ -0,0 +1,19 @@
++#as: -march=rv64ic
++#objdump: -drw
++
++.*:[ 	]+file format .*
++
++
++Disassembly of section .text:
++
++0+ <target>:
++[ 	]+[0-9a-f]+:[ 	]+c001[ 	]+beqz[ 	]+s0,0 <target>[ 	]+0: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+dcfd[ 	]+beqz[ 	]+s1,0 <target>[ 	]+2: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+fc75[ 	]+bnez[ 	]+s0,0 <target>[ 	]+4: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+fced[ 	]+bnez[ 	]+s1,0 <target>[ 	]+6: R_RISCV_RVC_BRANCH	.*
++[ 	]+[0-9a-f]+:[ 	]+bfe5[ 	]+j[ 	]+0 <target>[ 	]+8: R_RISCV_RVC_JUMP	.*
++[ 	]+[0-9a-f]+:[ 	]+ff7ff0ef[ 	]+jal[ 	]+0 <target>[ 	]+a: R_RISCV_JAL	.*
++[ 	]+[0-9a-f]+:[ 	]+9302[ 	]+jalr[ 	]+t1
++[ 	]+[0-9a-f]+:[ 	]+8382[ 	]+jr[ 	]+t2
++[ 	]+[0-9a-f]+:[ 	]+8082[ 	]+ret
++#...
+--- /dev/null
++++ b/gas/testsuite/gas/riscv/c-branch.s
+@@ -0,0 +1,11 @@
++	.text
++target:
++	beq	x8, x0, target
++	beqz	x9, target
++	bne	x8, x0, target
++	bnez	x9, target
++	j	target
++	jal	target
++	jalr	x6
++	jr	x7
++	ret
+--- a/opcodes/riscv-opc.c
++++ b/opcodes/riscv-opc.c
+@@ -340,9 +340,9 @@ const struct riscv_opcode riscv_opcodes[
+ {"jalr",        0, INSN_CLASS_I, "d,s,j",     MATCH_JALR, MASK_JALR, match_opcode, INSN_JSR },
+ {"j",           0, INSN_CLASS_C, "Ca",        MATCH_C_J, MASK_C_J, match_opcode, INSN_ALIAS|INSN_BRANCH },
+ {"j",           0, INSN_CLASS_I, "a",         MATCH_JAL, MASK_JAL|MASK_RD, match_opcode, INSN_ALIAS|INSN_BRANCH },
++{"jal",        32, INSN_CLASS_C, "Ca",        MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS|INSN_JSR },
+ {"jal",         0, INSN_CLASS_I, "a",         MATCH_JAL|(X_RA << OP_SH_RD), MASK_JAL|MASK_RD, match_opcode, INSN_ALIAS|INSN_JSR },
+ {"jal",         0, INSN_CLASS_I, "d,a",       MATCH_JAL, MASK_JAL, match_opcode, INSN_JSR },
+-{"jal",        32, INSN_CLASS_C, "Ca",        MATCH_C_JAL, MASK_C_JAL, match_opcode, INSN_ALIAS|INSN_JSR },
+ {"call",        0, INSN_CLASS_I, "d,c",       (X_T1 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
+ {"call",        0, INSN_CLASS_I, "c",         (X_RA << OP_SH_RS1)|(X_RA << OP_SH_RD), (int) M_CALL, match_never, INSN_MACRO },
+ {"tail",        0, INSN_CLASS_I, "c",         (X_T1 << OP_SH_RS1), (int) M_CALL, match_never, INSN_MACRO },
diff --git a/toolchain/binutils/patches/2.40/034-bpf-fix-error-conversion-from-long-unsigned-int-to-u.patch b/toolchain/binutils/patches/2.40/034-bpf-fix-error-conversion-from-long-unsigned-int-to-u.patch
new file mode 100644
index 0000000..d4317cd
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/034-bpf-fix-error-conversion-from-long-unsigned-int-to-u.patch
@@ -0,0 +1,209 @@
+From 3e888977f165594cf44dbe8f67e3a4960b22c11f Mon Sep 17 00:00:00 2001
+From: "Guillermo E. Martinez" <guillermo.e.martinez@oracle.com>
+Date: Fri, 3 Feb 2023 11:17:49 -0600
+Subject: [PATCH 34/50] bpf: fix error conversion from long unsigned int to
+ unsigned int [-Werror=overflow]
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Regenerating BPF target using the maintainer mode emits:
+.../opcodes/bpf-opc.c:57:11: error: conversion from ‘long unsigned int’ to ‘unsigned int’ changes value from ‘18446744073709486335’ to ‘4294902015’ [-Werror=overflow]
+  57 |   64, 64, 0xffffffffffff00ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+
+The use of a narrow size to handle the mask CGEN in instruction format
+is causing this error.  Additionally eBPF `call' instructions
+constructed by expressions using symbols (BPF_PSEUDO_CALL) emits
+annotations in `src' field of the instruction, used to identify BPF
+target endianness.
+
+cpu/
+	* bpf.cpu (define-call-insn): Remove `src' field from
+	instruction mask.
+
+include/
+	*opcode/cge.h (CGEN_IFMT): Adjust mask bit width.
+
+opcodes/
+	* bpf-opc.c: Regenerate.
+
+(cherry picked from commit 7f6ebecd56e690012b05af0a492280765b17f186)
+---
+ cpu/bpf.cpu           |  2 +-
+ include/opcode/cgen.h |  2 +-
+ opcodes/bpf-opc.c     | 54 +++++++++++++++++++++++--------------------
+ opcodes/cgen-dis.c    |  2 +-
+ 4 files changed, 32 insertions(+), 28 deletions(-)
+
+--- a/cpu/bpf.cpu
++++ b/cpu/bpf.cpu
+@@ -768,7 +768,7 @@
+        "call"
+        (endian-isas x-endian)
+        "call $disp32"
+-       (+ disp32 (f-offset16 0) (f-regs 0)
++       (+ disp32 (f-offset16 0) (.sym src x-endian) ((.sym f-dst x-endian) 0)
+           OP_CLASS_JMP OP_SRC_K OP_CODE_CALL)
+        (c-call VOID
+                "bpfbf_call" disp32 (ifield (.sym f-src x-endian)))
+--- a/include/opcode/cgen.h
++++ b/include/opcode/cgen.h
+@@ -914,7 +914,7 @@ typedef struct
+      Each insn's value is stored with the insn.
+      The first step in recognizing an insn for disassembly is
+      (opcode & mask) == value.  */
+-  CGEN_INSN_INT mask;
++  CGEN_INSN_LGUINT mask;
+ #define CGEN_IFMT_MASK(ifmt) ((ifmt)->mask)
+ 
+   /* Instruction fields.
+--- a/opcodes/bpf-opc.c
++++ b/opcodes/bpf-opc.c
+@@ -50,99 +50,103 @@ static const CGEN_IFMT ifmt_empty ATTRIB
+ };
+ 
+ static const CGEN_IFMT ifmt_addile ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_addrle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffffffff00ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_negle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfffffffffffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_addibe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_addrbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffffffff00ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_negbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffffffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_endlele ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_endlebe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_lddwle ATTRIBUTE_UNUSED = {
+-  64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 128, 0xfffff0ff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_lddwbe ATTRIBUTE_UNUSED = {
+-  64, 128, 0xff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 128, 0xffff0fff, { { F (F_IMM64) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ldabsw ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ldindwle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ldindwbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ldxwle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ldxwbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_stble ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xf0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_DSTLE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_stbbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_MODE) }, { F (F_OP_SIZE) }, { F (F_SRCBE) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_jeqile ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xf0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_jeqrle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_jeqibe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xfff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_jeqrbe ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff000000ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_callle ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffff0fff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_SRCLE) }, { F (F_OP_CODE) }, { F (F_DSTLE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++};
++
++static const CGEN_IFMT ifmt_callbe ATTRIBUTE_UNUSED = {
++  64, 64, 0xfffff0ff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_DSTBE) }, { F (F_OP_CODE) }, { F (F_SRCBE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_ja ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffff0000ffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ static const CGEN_IFMT ifmt_exit ATTRIBUTE_UNUSED = {
+-  64, 64, 0xff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
++  64, 64, 0xffffffffffffffff, { { F (F_IMM32) }, { F (F_OFFSET16) }, { F (F_REGS) }, { F (F_OP_CODE) }, { F (F_OP_SRC) }, { F (F_OP_CLASS) }, { 0 } }
+ };
+ 
+ #undef F
+@@ -1646,7 +1650,7 @@ static const CGEN_OPCODE bpf_cgen_insn_o
+   {
+     { 0, 0, 0, 0 },
+     { { MNEM, ' ', OP (DISP32), 0 } },
+-    & ifmt_callle, { 0x85 }
++    & ifmt_callbe, { 0x85 }
+   },
+ /* call $dstle */
+   {
+--- a/opcodes/cgen-dis.c
++++ b/opcodes/cgen-dis.c
+@@ -39,7 +39,7 @@ static void		 add_insn_to_hash_chain (CG
+ static int
+ count_decodable_bits (const CGEN_INSN *insn)
+ {
+-  unsigned mask = CGEN_INSN_BASE_MASK (insn);
++  CGEN_INSN_LGUINT mask = CGEN_INSN_BASE_MASK (insn);
+ #if GCC_VERSION >= 3004
+   return __builtin_popcount (mask);
+ #else
diff --git a/toolchain/binutils/patches/2.40/035-Pass-JANSSON_LIBS-and-ZSTD_LIBS-to-ld-bootstrap-boot.patch b/toolchain/binutils/patches/2.40/035-Pass-JANSSON_LIBS-and-ZSTD_LIBS-to-ld-bootstrap-boot.patch
new file mode 100644
index 0000000..3741c08
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/035-Pass-JANSSON_LIBS-and-ZSTD_LIBS-to-ld-bootstrap-boot.patch
@@ -0,0 +1,50 @@
+From e1815414077347097e5bf0d75162add955e241d9 Mon Sep 17 00:00:00 2001
+From: Romain Geissler <romain.geissler@amadeus.com>
+Date: Sun, 5 Feb 2023 13:56:34 +0000
+Subject: [PATCH 35/50] Pass $JANSSON_LIBS and $ZSTD_LIBS to
+ ld-bootstrap/bootrap.exp
+
+---
+ ld/Makefile.am                          | 1 +
+ ld/Makefile.in                          | 1 +
+ ld/testsuite/ld-bootstrap/bootstrap.exp | 4 ++--
+ 3 files changed, 4 insertions(+), 2 deletions(-)
+
+--- a/ld/Makefile.am
++++ b/ld/Makefile.am
+@@ -992,6 +992,7 @@ check-DEJAGNU: site.exp
+ 		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+ 		OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(TESTCTFLIB) $(ZLIB)" \
+ 		SFRAMELIB="$(TESTSFRAMELIB)" \
++		JANSSON_LIBS="$(JANSSON_LIBS)" ZSTD_LIBS="$(ZSTD_LIBS)" \
+ 		LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \
+ 		DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \
+ 		$(RUNTESTFLAGS); \
+--- a/ld/Makefile.in
++++ b/ld/Makefile.in
+@@ -2645,6 +2645,7 @@ check-DEJAGNU: site.exp
+ 		CXXFLAGS_FOR_TARGET="$(CXXFLAGS_FOR_TARGET)" \
+ 		OFILES="$(OFILES)" BFDLIB="$(TESTBFDLIB)" CTFLIB="$(TESTCTFLIB) $(ZLIB)" \
+ 		SFRAMELIB="$(TESTSFRAMELIB)" \
++		JANSSON_LIBS="$(JANSSON_LIBS)" ZSTD_LIBS="$(ZSTD_LIBS)" \
+ 		LIBIBERTY="$(LIBIBERTY) $(LIBINTL)" LIBS="$(LIBS)" \
+ 		DO_COMPARE="`echo '$(do_compare)' | sed -e 's,\\$$,,g'`" \
+ 		$(RUNTESTFLAGS); \
+--- a/ld/testsuite/ld-bootstrap/bootstrap.exp
++++ b/ld/testsuite/ld-bootstrap/bootstrap.exp
+@@ -162,13 +162,13 @@ foreach flags $test_flags {
+     }
+ 
+     if { [lindex [remote_exec build grep "-q \"HAVE_ZSTD 1\" config.h" ] 0] == 0 } then {
+-	set extralibs "$extralibs -lzstd"
++	set extralibs "$extralibs $ZSTD_LIBS"
+     }
+ 
+     # Check if the system's jansson library is used. If so, the object files will
+     # be using symbols from it, so link to it.
+     if { [lindex [remote_exec build grep "-q \"HAVE_JANSSON 1\" config.h" ] 0] == 0 } then {
+-	set extralibs "$extralibs -ljansson"
++	set extralibs "$extralibs $JANSSON_LIBS"
+     }
+ 
+     # Plugin support requires linking with libdl.
diff --git a/toolchain/binutils/patches/2.40/036-Regen-config-files.patch b/toolchain/binutils/patches/2.40/036-Regen-config-files.patch
new file mode 100644
index 0000000..1c80dde
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/036-Regen-config-files.patch
@@ -0,0 +1,714 @@
+From 1fc096a4c590f28e0efb1823cdca653f2db9de74 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Mon, 6 Feb 2023 10:48:59 +1030
+Subject: [PATCH 36/50] Regen config files
+
+For the version update to 2.40.0
+---
+ bfd/configure                  | 20 ++++++++++----------
+ binutils/configure             | 20 ++++++++++----------
+ gas/configure                  | 20 ++++++++++----------
+ gprof/configure                | 20 ++++++++++----------
+ gprofng/configure              | 20 ++++++++++----------
+ gprofng/doc/version.texi       |  8 ++++----
+ gprofng/libcollector/configure | 20 ++++++++++----------
+ intl/configure                 |  3 +++
+ ld/configure                   | 20 ++++++++++----------
+ opcodes/configure              | 20 ++++++++++----------
+ 10 files changed, 87 insertions(+), 84 deletions(-)
+
+--- a/bfd/configure
++++ b/bfd/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for bfd 2.40.
++# Generated by GNU Autoconf 2.69 for bfd 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='bfd'
+ PACKAGE_TARNAME='bfd'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='bfd 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='bfd 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1400,7 +1400,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures bfd 2.40 to adapt to many kinds of systems.
++\`configure' configures bfd 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1471,7 +1471,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of bfd 2.40:";;
++     short | recursive ) echo "Configuration of bfd 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1608,7 +1608,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-bfd configure 2.40
++bfd configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2202,7 +2202,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by bfd $as_me 2.40, which was
++It was created by bfd $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3184,7 +3184,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='bfd'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -15906,7 +15906,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by bfd $as_me 2.40, which was
++This file was extended by bfd $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -15972,7 +15972,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-bfd config.status 2.40
++bfd config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/binutils/configure
++++ b/binutils/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for binutils 2.40.
++# Generated by GNU Autoconf 2.69 for binutils 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='binutils'
+ PACKAGE_TARNAME='binutils'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='binutils 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='binutils 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1401,7 +1401,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures binutils 2.40 to adapt to many kinds of systems.
++\`configure' configures binutils 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1472,7 +1472,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of binutils 2.40:";;
++     short | recursive ) echo "Configuration of binutils 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1631,7 +1631,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-binutils configure 2.40
++binutils configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2099,7 +2099,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by binutils $as_me 2.40, which was
++It was created by binutils $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3081,7 +3081,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='binutils'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -15326,7 +15326,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by binutils $as_me 2.40, which was
++This file was extended by binutils $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -15392,7 +15392,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-binutils config.status 2.40
++binutils config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gas/configure
++++ b/gas/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gas 2.40.
++# Generated by GNU Autoconf 2.69 for gas 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gas'
+ PACKAGE_TARNAME='gas'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='gas 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='gas 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1381,7 +1381,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gas 2.40 to adapt to many kinds of systems.
++\`configure' configures gas 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1452,7 +1452,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gas 2.40:";;
++     short | recursive ) echo "Configuration of gas 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1600,7 +1600,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gas configure 2.40
++gas configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2011,7 +2011,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gas $as_me 2.40, which was
++It was created by gas $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -2990,7 +2990,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gas'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -14910,7 +14910,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gas $as_me 2.40, which was
++This file was extended by gas $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -14976,7 +14976,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gas config.status 2.40
++gas config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprof/configure
++++ b/gprof/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprof 2.40.
++# Generated by GNU Autoconf 2.69 for gprof 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprof'
+ PACKAGE_TARNAME='gprof'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='gprof 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='gprof 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1338,7 +1338,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprof 2.40 to adapt to many kinds of systems.
++\`configure' configures gprof 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1409,7 +1409,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprof 2.40:";;
++     short | recursive ) echo "Configuration of gprof 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1520,7 +1520,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprof configure 2.40
++gprof configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -1885,7 +1885,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprof $as_me 2.40, which was
++It was created by gprof $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -2864,7 +2864,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprof'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -12572,7 +12572,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprof $as_me 2.40, which was
++This file was extended by gprof $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -12638,7 +12638,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprof config.status 2.40
++gprof config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprofng/configure
++++ b/gprofng/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprofng 2.40.
++# Generated by GNU Autoconf 2.69 for gprofng 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprofng'
+ PACKAGE_TARNAME='gprofng'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='gprofng 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='gprofng 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1364,7 +1364,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprofng 2.40 to adapt to many kinds of systems.
++\`configure' configures gprofng 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1435,7 +1435,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprofng 2.40:";;
++     short | recursive ) echo "Configuration of gprofng 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1549,7 +1549,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprofng configure 2.40
++gprofng configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2081,7 +2081,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprofng $as_me 2.40, which was
++It was created by gprofng $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3054,7 +3054,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprofng'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -17528,7 +17528,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprofng $as_me 2.40, which was
++This file was extended by gprofng $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -17594,7 +17594,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprofng config.status 2.40
++gprofng config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/gprofng/doc/version.texi
++++ b/gprofng/doc/version.texi
+@@ -1,4 +1,4 @@
+-@set UPDATED 5 January 2023
+-@set UPDATED-MONTH January 2023
+-@set EDITION 2.40
+-@set VERSION 2.40
++@set UPDATED 1 February 2023
++@set UPDATED-MONTH February 2023
++@set EDITION 2.40.0
++@set VERSION 2.40.0
+--- a/gprofng/libcollector/configure
++++ b/gprofng/libcollector/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for gprofng 2.40.
++# Generated by GNU Autoconf 2.69 for gprofng 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='gprofng'
+ PACKAGE_TARNAME='gprofng'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='gprofng 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='gprofng 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1325,7 +1325,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures gprofng 2.40 to adapt to many kinds of systems.
++\`configure' configures gprofng 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1396,7 +1396,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of gprofng 2.40:";;
++     short | recursive ) echo "Configuration of gprofng 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1505,7 +1505,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-gprofng configure 2.40
++gprofng configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -1991,7 +1991,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by gprofng $as_me 2.40, which was
++It was created by gprofng $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -2968,7 +2968,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='gprofng'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -16098,7 +16098,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by gprofng $as_me 2.40, which was
++This file was extended by gprofng $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -16164,7 +16164,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-gprofng config.status 2.40
++gprofng config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/intl/configure
++++ b/intl/configure
+@@ -6857,6 +6857,9 @@ case "${host}" in
+ 	# sets the default TLS model and affects inlining.
+ 	PICFLAG=-fPIC
+ 	;;
++    loongarch*-*-*)
++	PICFLAG=-fpic
++	;;
+     mips-sgi-irix6*)
+ 	# PIC is the default.
+ 	;;
+--- a/ld/configure
++++ b/ld/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for ld 2.40.
++# Generated by GNU Autoconf 2.69 for ld 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='ld'
+ PACKAGE_TARNAME='ld'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='ld 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='ld 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1423,7 +1423,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures ld 2.40 to adapt to many kinds of systems.
++\`configure' configures ld 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1494,7 +1494,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of ld 2.40:";;
++     short | recursive ) echo "Configuration of ld 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1661,7 +1661,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-ld configure 2.40
++ld configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2376,7 +2376,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by ld $as_me 2.40, which was
++It was created by ld $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3359,7 +3359,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='ld'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -18083,7 +18083,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by ld $as_me 2.40, which was
++This file was extended by ld $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -18149,7 +18149,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-ld config.status 2.40
++ld config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
+--- a/opcodes/configure
++++ b/opcodes/configure
+@@ -1,6 +1,6 @@
+ #! /bin/sh
+ # Guess values for system-dependent variables and create Makefiles.
+-# Generated by GNU Autoconf 2.69 for opcodes 2.40.
++# Generated by GNU Autoconf 2.69 for opcodes 2.40.0.
+ #
+ #
+ # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@@ -587,8 +587,8 @@ MAKEFLAGS=
+ # Identity of this package.
+ PACKAGE_NAME='opcodes'
+ PACKAGE_TARNAME='opcodes'
+-PACKAGE_VERSION='2.40'
+-PACKAGE_STRING='opcodes 2.40'
++PACKAGE_VERSION='2.40.0'
++PACKAGE_STRING='opcodes 2.40.0'
+ PACKAGE_BUGREPORT=''
+ PACKAGE_URL=''
+ 
+@@ -1360,7 +1360,7 @@ if test "$ac_init_help" = "long"; then
+   # Omit some internal or obsolete options to make the list less imposing.
+   # This message is too long to be a string in the A/UX 3.1 sh.
+   cat <<_ACEOF
+-\`configure' configures opcodes 2.40 to adapt to many kinds of systems.
++\`configure' configures opcodes 2.40.0 to adapt to many kinds of systems.
+ 
+ Usage: $0 [OPTION]... [VAR=VALUE]...
+ 
+@@ -1431,7 +1431,7 @@ fi
+ 
+ if test -n "$ac_init_help"; then
+   case $ac_init_help in
+-     short | recursive ) echo "Configuration of opcodes 2.40:";;
++     short | recursive ) echo "Configuration of opcodes 2.40.0:";;
+    esac
+   cat <<\_ACEOF
+ 
+@@ -1545,7 +1545,7 @@ fi
+ test -n "$ac_init_help" && exit $ac_status
+ if $ac_init_version; then
+   cat <<\_ACEOF
+-opcodes configure 2.40
++opcodes configure 2.40.0
+ generated by GNU Autoconf 2.69
+ 
+ Copyright (C) 2012 Free Software Foundation, Inc.
+@@ -2139,7 +2139,7 @@ cat >config.log <<_ACEOF
+ This file contains any messages produced by compilers while
+ running configure, to aid debugging if configure makes a mistake.
+ 
+-It was created by opcodes $as_me 2.40, which was
++It was created by opcodes $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   $ $0 $@
+@@ -3118,7 +3118,7 @@ fi
+ 
+ # Define the identity of the package.
+  PACKAGE='opcodes'
+- VERSION='2.40'
++ VERSION='2.40.0'
+ 
+ 
+ cat >>confdefs.h <<_ACEOF
+@@ -13191,7 +13191,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_wri
+ # report actual input values of CONFIG_FILES etc. instead of their
+ # values after options handling.
+ ac_log="
+-This file was extended by opcodes $as_me 2.40, which was
++This file was extended by opcodes $as_me 2.40.0, which was
+ generated by GNU Autoconf 2.69.  Invocation command line was
+ 
+   CONFIG_FILES    = $CONFIG_FILES
+@@ -13257,7 +13257,7 @@ _ACEOF
+ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ ac_cs_version="\\
+-opcodes config.status 2.40
++opcodes config.status 2.40.0
+ configured by $0, generated by GNU Autoconf 2.69,
+   with options \\"\$ac_cs_config\\"
+ 
diff --git a/toolchain/binutils/patches/2.40/040-configure-remove-dependencies-on-gmp-and-mpfr-when-g.patch b/toolchain/binutils/patches/2.40/040-configure-remove-dependencies-on-gmp-and-mpfr-when-g.patch
new file mode 100644
index 0000000..261acb5
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/040-configure-remove-dependencies-on-gmp-and-mpfr-when-g.patch
@@ -0,0 +1,51 @@
+From 17294931e3e361bee6810b1a39493e214b38c5e5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= <chigot@adacore.com>
+Date: Tue, 3 Jan 2023 14:24:43 +0100
+Subject: [PATCH 40/50] configure: remove dependencies on gmp and mpfr when gdb
+ is disabled
+
+Since 991180627851801f1999d1ebbc0e569a17e47c74, the configure checks
+about GMP and MPFR for gdb builds have been moved to the toplevel
+configure.
+However, it doesn't take into account the --disable-gdb option. Meaning
+that a build without gdb will require these libraries even if not
+needed.
+
+ChangeLog:
+
+	* configure.ac: Skip GMP and MPFR when --disable-gdb is
+	provided.
+	* configure: Regenerate.
+
+(cherry picked from commit 5fb0e308577143ceb313fde5538dc9ecb038f29f)
+---
+ configure    | 4 +++-
+ configure.ac | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/configure
++++ b/configure
+@@ -8032,7 +8032,9 @@ if test -d ${srcdir}/gcc ; then
+   require_mpc=yes
+ fi
+ if test -d ${srcdir}/gdb ; then
+-  require_gmp=yes
++  if test "x$enable_gdb" != xno; then
++   require_gmp=yes
++  fi
+ fi
+ 
+ gmplibs="-lmpfr -lgmp"
+--- a/configure.ac
++++ b/configure.ac
+@@ -1585,7 +1585,9 @@ if test -d ${srcdir}/gcc ; then
+   require_mpc=yes
+ fi
+ if test -d ${srcdir}/gdb ; then
+-  require_gmp=yes
++  if test "x$enable_gdb" != xno; then
++   require_gmp=yes
++  fi
+ fi
+ 
+ gmplibs="-lmpfr -lgmp"
diff --git a/toolchain/binutils/patches/2.40/046-gas-correct-symbol-name-comparison-in-.startof.-.siz.patch b/toolchain/binutils/patches/2.40/046-gas-correct-symbol-name-comparison-in-.startof.-.siz.patch
new file mode 100644
index 0000000..4e31bb4
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/046-gas-correct-symbol-name-comparison-in-.startof.-.siz.patch
@@ -0,0 +1,46 @@
+From b2bc62b7b4e7638c3a249d2d2728ceb4d5f2b22c Mon Sep 17 00:00:00 2001
+From: Jan Beulich <jbeulich@suse.com>
+Date: Tue, 14 Feb 2023 08:35:02 +0100
+Subject: [PATCH 46/50] gas: correct symbol name comparison in
+ .startof./.sizeof. handling
+
+In 162c6aef1f3a ("gas: fold symbol table entries generated for
+.startof.() / .sizeof.()") I screwed up quite badly, inverting the case
+sensitive and case insensitive comparison functions.
+---
+ gas/expr.c                      | 4 ++--
+ gas/testsuite/gas/elf/startof.d | 2 ++
+ gas/testsuite/gas/elf/startof.s | 3 +++
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/gas/expr.c
++++ b/gas/expr.c
+@@ -149,8 +149,8 @@ symbol_lookup_or_make (const char *name,
+ 
+     name = S_GET_NAME (symbolP);
+     if ((symbols_case_sensitive
+-	 ? strcasecmp (buf, name)
+-	 : strcmp (buf, name)) == 0)
++	 ? strcmp (buf, name)
++	 : strcasecmp (buf, name)) == 0)
+       {
+ 	free (buf);
+ 	return symbolP;
+--- a/gas/testsuite/gas/elf/startof.d
++++ b/gas/testsuite/gas/elf/startof.d
+@@ -7,4 +7,6 @@ Symbol table .*
+ #...
+      [1-8]: 0+ .* UND \.startof\.\.text
+      [2-9]: 0+ .* UND \.sizeof\.\.text
++ +[1-9][0-9]*: 0+ .* UND \.startof\.\.Text
++ +[1-9][0-9]*: 0+ .* UND \.sizeof\.\.TEXT
+ #pass
+--- a/gas/testsuite/gas/elf/startof.s
++++ b/gas/testsuite/gas/elf/startof.s
+@@ -4,3 +4,6 @@
+ 	.dc.a	0
+ 	.dc.a	.sizeof.(.text)
+ 	.dc.a	.startof.(.text)
++	.dc.a	0
++	.dc.a	.startof.(.Text)
++	.dc.a	.sizeof.(.TEXT)
diff --git a/toolchain/binutils/patches/2.40/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.40/300-001_ld_makefile_patch.patch
new file mode 100644
index 0000000..2dafd92
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/300-001_ld_makefile_patch.patch
@@ -0,0 +1,22 @@
+--- a/ld/Makefile.am
++++ b/ld/Makefile.am
+@@ -50,7 +50,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ 
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
+--- a/ld/Makefile.in
++++ b/ld/Makefile.in
+@@ -573,7 +573,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CLFAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ BASEDIR = $(srcdir)/..
+ BFDDIR = $(BASEDIR)/bfd
+ INCDIR = $(BASEDIR)/include
diff --git a/toolchain/binutils/patches/2.40/400-mips_no_dynamic_linking_sym.patch b/toolchain/binutils/patches/2.40/400-mips_no_dynamic_linking_sym.patch
new file mode 100644
index 0000000..aeb5a99
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/400-mips_no_dynamic_linking_sym.patch
@@ -0,0 +1,18 @@
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -8119,6 +8119,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
+       bh = NULL;
++      if (0) {
+       if (!(_bfd_generic_link_add_one_symbol
+ 	    (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
+ 	     NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
+@@ -8131,6 +8132,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ 	return false;
++      }
+ 
+       if (! mips_elf_hash_table (info)->use_rld_obj_head)
+ 	{
diff --git a/toolchain/binutils/patches/2.40/500-Change-default-emulation-for-mips64-linux.patch b/toolchain/binutils/patches/2.40/500-Change-default-emulation-for-mips64-linux.patch
new file mode 100644
index 0000000..14a18a1
--- /dev/null
+++ b/toolchain/binutils/patches/2.40/500-Change-default-emulation-for-mips64-linux.patch
@@ -0,0 +1,38 @@
+--- a/bfd/config.bfd
++++ b/bfd/config.bfd
+@@ -944,12 +944,12 @@ case "${targ}" in
+     targ_selvecs="mips_elf32_le_vec mips_elf64_be_vec mips_elf64_le_vec mips_ecoff_be_vec mips_ecoff_le_vec"
+     ;;
+   mips64*el-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_le_vec
+-    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_le_vec mips_elf64_trad_be_vec"
++    targ_defvec=mips_elf64_trad_le_vec
++    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_be_vec"
+     ;;
+   mips64*-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_be_vec
+-    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
++    targ_defvec=mips_elf64_trad_be_vec
++    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_le_vec"
+     ;;
+   mips*el-*-linux*)
+     targ_defvec=mips_elf32_trad_le_vec
+--- a/ld/configure.tgt
++++ b/ld/configure.tgt
+@@ -585,12 +585,12 @@ mips*-*-vxworks*)	targ_emul=elf32ebmipvx
+ 			;;
+ mips*-*-windiss)	targ_emul=elf32mipswindiss
+ 			;;
+-mips64*el-*-linux-*)	targ_emul=elf32ltsmipn32
+-			targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
++mips64*el-*-linux-*)	targ_emul=elf64ltsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32ltsmip elf32btsmip elf64btsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+-mips64*-*-linux-*)	targ_emul=elf32btsmipn32
+-			targ_extra_emuls="elf32ltsmipn32 elf32btsmip elf32ltsmip elf64btsmip elf64ltsmip"
++mips64*-*-linux-*)	targ_emul=elf64btsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip elf64ltsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+ mips*el-*-linux-*)	targ_emul=elf32ltsmip
diff --git a/toolchain/binutils/patches/2.42/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch b/toolchain/binutils/patches/2.42/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch
new file mode 100644
index 0000000..96f3971
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/001-PR-30569-always-call-elf_backend_size_dynamic_sectio.patch
@@ -0,0 +1,2228 @@
+From af969b14aedcc0ae27dcefab4327ff2d153dec8b Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Thu, 28 Mar 2024 19:25:42 +1030
+Subject: [PATCH 1/2] PR 30569, always call elf_backend_size_dynamic_sections
+
+This largely mechanical patch is preparation for a followup patch.
+
+For quite some time I've thought that it would be useful to call
+elf_backend_size_dynamic_sections even when no dynamic objects are
+seen by the linker.  That's what this patch does, with some renaming.
+There are no functional changes to the linker, just a move of the
+dynobj test in bfd_elf_size_dynamic_sections to target backend
+functions, replacing the asserts/aborts already there.  No doubt some
+of the current always_size_sections functions could be moved to
+size_dynamic_sections but I haven't made that change.
+
+Because both hooks are now always called, I have renamed
+always_size_sections to early_size_sections and size_dynamic_sections
+to late_size_sections.  I condisdered calling late_size_sections plain
+size_sections, since this is the usual target dynamic section sizing
+hook, but decided that searching the sources for "size_sections" would
+then hit early_size_sections and other functions.
+---
+ bfd/elf-bfd.h          | 35 +++++++++++++++++------------------
+ bfd/elf-m10300.c       | 11 ++++++-----
+ bfd/elf32-arc.c        |  9 +++++----
+ bfd/elf32-arm.c        | 15 ++++++++-------
+ bfd/elf32-bfin.c       | 31 ++++++++++++++++---------------
+ bfd/elf32-cr16.c       | 11 ++++++-----
+ bfd/elf32-cris.c       | 13 +++++++------
+ bfd/elf32-csky.c       |  8 ++++----
+ bfd/elf32-frv.c        | 23 ++++++++++++-----------
+ bfd/elf32-hppa.c       |  8 ++++----
+ bfd/elf32-i386.c       |  7 +++----
+ bfd/elf32-lm32.c       | 15 ++++++++-------
+ bfd/elf32-m32c.c       |  8 ++++----
+ bfd/elf32-m32r.c       | 11 ++++++-----
+ bfd/elf32-m68k.c       | 16 ++++++++--------
+ bfd/elf32-metag.c      |  8 ++++----
+ bfd/elf32-microblaze.c |  9 +++++----
+ bfd/elf32-mips.c       |  6 ++----
+ bfd/elf32-nds32.c      |  9 +++++----
+ bfd/elf32-nios2.c      | 15 ++++++++-------
+ bfd/elf32-or1k.c       |  9 +++++----
+ bfd/elf32-ppc.c        | 11 ++++++-----
+ bfd/elf32-rl78.c       |  8 ++++----
+ bfd/elf32-s390.c       | 10 +++++-----
+ bfd/elf32-score.c      | 35 ++++++++++++++++++-----------------
+ bfd/elf32-score.h      |  4 ++--
+ bfd/elf32-score7.c     | 13 +++++++------
+ bfd/elf32-sh.c         | 15 +++++++--------
+ bfd/elf32-sparc.c      |  3 +--
+ bfd/elf32-tic6x.c      | 14 +++++++-------
+ bfd/elf32-tilegx.c     |  2 +-
+ bfd/elf32-tilepro.c    | 11 +++++------
+ bfd/elf32-vax.c        | 16 +++++++---------
+ bfd/elf32-xstormy16.c  |  8 ++++----
+ bfd/elf32-xtensa.c     | 13 ++++++-------
+ bfd/elf64-alpha.c      | 19 ++++++++++---------
+ bfd/elf64-hppa.c       | 11 ++++-------
+ bfd/elf64-ia64-vms.c   | 13 +++++++------
+ bfd/elf64-mips.c       |  8 ++++----
+ bfd/elf64-ppc.c        | 12 ++++++------
+ bfd/elf64-s390.c       | 10 +++++-----
+ bfd/elf64-sparc.c      |  4 ++--
+ bfd/elf64-tilegx.c     |  2 +-
+ bfd/elf64-x86-64.c     |  7 +++----
+ bfd/elflink.c          |  9 ++++-----
+ bfd/elfn32-mips.c      |  6 ++----
+ bfd/elfnn-aarch64.c    | 21 +++++++++++----------
+ bfd/elfnn-ia64.c       | 11 ++++++-----
+ bfd/elfnn-kvx.c        | 19 +++++++++----------
+ bfd/elfnn-loongarch.c  |  9 +++++----
+ bfd/elfnn-riscv.c      |  7 ++++---
+ bfd/elfxx-mips.c       | 15 ++++++++-------
+ bfd/elfxx-mips.h       |  4 ++--
+ bfd/elfxx-sparc.c      |  7 ++++---
+ bfd/elfxx-sparc.h      |  2 +-
+ bfd/elfxx-target.h     | 12 ++++++------
+ bfd/elfxx-tilegx.c     |  7 ++++---
+ bfd/elfxx-tilegx.h     |  2 +-
+ bfd/elfxx-x86.c        |  8 ++++----
+ bfd/elfxx-x86.h        |  8 ++++----
+ ld/emultempl/vms.em    |  7 +++----
+ 61 files changed, 343 insertions(+), 337 deletions(-)
+
+--- a/bfd/elf-bfd.h
++++ b/bfd/elf-bfd.h
+@@ -1187,7 +1187,7 @@ struct elf_backend_data
+   /* The ADJUST_DYNAMIC_SYMBOL function is called by the ELF backend
+      linker for every symbol which is defined by a dynamic object and
+      referenced by a regular object.  This is called after all the
+-     input files have been seen, but before the SIZE_DYNAMIC_SECTIONS
++     input files have been seen, but before the LATE_SIZE_SECTIONS
+      function has been called.  The hash table entry should be
+      bfd_link_hash_defined ore bfd_link_hash_defweak, and it should be
+      defined in a section from a dynamic object.  Dynamic object
+@@ -1199,24 +1199,23 @@ struct elf_backend_data
+   bool (*elf_backend_adjust_dynamic_symbol)
+     (struct bfd_link_info *info, struct elf_link_hash_entry *h);
+ 
+-  /* The ALWAYS_SIZE_SECTIONS function is called by the backend linker
+-     after all the linker input files have been seen but before the
+-     section sizes have been set.  This is called after
+-     ADJUST_DYNAMIC_SYMBOL, but before SIZE_DYNAMIC_SECTIONS.  */
+-  bool (*elf_backend_always_size_sections)
++  /* The EARLY_SIZE_SECTIONS and LATE_SIZE_SECTIONS functions are
++     called by the backend linker after all linker input files have
++     been seen and sections have been assigned to output sections, but
++     before the section sizes have been set.  Both of these functions
++     are called even when no dynamic object is seen by the linker.
++     Between them, they must set the sizes of the dynamic sections and
++     other backend specific sections, and may fill in their contents.
++     Most backends need only use LATE_SIZE_SECTIONS.
++     EARLY_SIZE_SECTIONS is called before --export-dynamic makes some
++     symbols dynamic and before ADJUST_DYNAMIC_SYMBOL processes
++     dynamic symbols, LATE_SIZE_SECTIONS afterwards.  The generic ELF
++     linker can handle the .dynsym, .dynstr and .hash sections.
++     Besides those, these functions must handle the .interp section
++     and any other sections created by CREATE_DYNAMIC_SECTIONS.  */
++  bool (*elf_backend_early_size_sections)
+     (bfd *output_bfd, struct bfd_link_info *info);
+-
+-  /* The SIZE_DYNAMIC_SECTIONS function is called by the ELF backend
+-     linker after all the linker input files have been seen but before
+-     the sections sizes have been set.  This is called after
+-     ADJUST_DYNAMIC_SYMBOL has been called on all appropriate symbols.
+-     It is only called when linking against a dynamic object.  It must
+-     set the sizes of the dynamic sections, and may fill in their
+-     contents as well.  The generic ELF linker can handle the .dynsym,
+-     .dynstr and .hash sections.  This function must handle the
+-     .interp section and any sections created by the
+-     CREATE_DYNAMIC_SECTIONS entry point.  */
+-  bool (*elf_backend_size_dynamic_sections)
++  bool (*elf_backend_late_size_sections)
+     (bfd *output_bfd, struct bfd_link_info *info);
+ 
+   /* The STRIP_ZERO_SIZED_DYNAMIC_SECTIONS function is called by the
+--- a/bfd/elf-m10300.c
++++ b/bfd/elf-m10300.c
+@@ -5015,8 +5015,8 @@ _bfd_mn10300_elf_adjust_dynamic_symbol (
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-_bfd_mn10300_elf_size_dynamic_sections (bfd * output_bfd,
+-					struct bfd_link_info * info)
++_bfd_mn10300_elf_late_size_sections (bfd * output_bfd,
++				     struct bfd_link_info * info)
+ {
+   struct elf32_mn10300_link_hash_table *htab = elf32_mn10300_hash_table (info);
+   bfd * dynobj;
+@@ -5024,7 +5024,8 @@ _bfd_mn10300_elf_size_dynamic_sections (
+   bool relocs;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5511,8 +5512,8 @@ mn10300_elf_mkobject (bfd *abfd)
+   _bfd_mn10300_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol \
+   _bfd_mn10300_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_mn10300_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_mn10300_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_symbol \
+   _bfd_mn10300_elf_finish_dynamic_symbol
+--- a/bfd/elf32-arc.c
++++ b/bfd/elf32-arc.c
+@@ -2715,8 +2715,8 @@ elf_arc_finish_dynamic_sections (bfd * o
+ 
+ /* Set the sizes of the dynamic sections.  */
+ static bool
+-elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++elf_arc_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			    struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -2724,7 +2724,8 @@ elf_arc_size_dynamic_sections (bfd *outp
+   struct elf_link_hash_table *htab = elf_hash_table (info);
+ 
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -3140,7 +3141,7 @@ arc_elf_relax_section (bfd *abfd, asecti
+ #define elf_backend_finish_dynamic_symbol    elf_arc_finish_dynamic_symbol
+ 
+ #define elf_backend_finish_dynamic_sections  elf_arc_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections    elf_arc_size_dynamic_sections
++#define elf_backend_late_size_sections       elf_arc_late_size_sections
+ 
+ #define elf_backend_can_gc_sections	1
+ #define elf_backend_want_got_plt	1
+--- a/bfd/elf32-arm.c
++++ b/bfd/elf32-arm.c
+@@ -16752,8 +16752,8 @@ bfd_elf32_arm_set_byteswap_code (struct
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_arm_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info * info)
++elf32_arm_late_size_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info * info)
+ {
+   bfd * dynobj;
+   asection * s;
+@@ -16766,7 +16766,9 @@ elf32_arm_size_dynamic_sections (bfd * o
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
++
+   check_use_blx (htab);
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+@@ -17138,8 +17140,7 @@ elf32_arm_size_dynamic_sections (bfd * o
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bool
+-elf32_arm_always_size_sections (bfd *output_bfd,
+-				struct bfd_link_info *info)
++elf32_arm_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+   struct elf32_arm_link_hash_table *htab;
+@@ -20341,8 +20342,8 @@ elf32_arm_backend_symbol_processing (bfd
+ #define elf_backend_create_dynamic_sections	elf32_arm_create_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	elf32_arm_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	elf32_arm_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	elf32_arm_size_dynamic_sections
+-#define elf_backend_always_size_sections	elf32_arm_always_size_sections
++#define elf_backend_late_size_sections		elf32_arm_late_size_sections
++#define elf_backend_early_size_sections		elf32_arm_early_size_sections
+ #define elf_backend_init_index_section		_bfd_elf_init_2_index_sections
+ #define elf_backend_init_file_header		elf32_arm_init_file_header
+ #define elf_backend_reloc_type_class		elf32_arm_reloc_type_class
+--- a/bfd/elf32-bfin.c
++++ b/bfd/elf32-bfin.c
+@@ -4027,8 +4027,8 @@ _bfinfdpic_size_got_plt (bfd *output_bfd
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_bfinfdpic_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++elf32_bfinfdpic_late_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -4037,7 +4037,8 @@ elf32_bfinfdpic_size_dynamic_sections (b
+ 
+   htab = elf_hash_table (info);
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -4086,7 +4087,7 @@ elf32_bfinfdpic_size_dynamic_sections (b
+ }
+ 
+ static bool
+-elf32_bfinfdpic_always_size_sections (bfd *output_bfd,
++elf32_bfinfdpic_early_size_sections (bfd *output_bfd,
+ 				     struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info)
+@@ -5123,15 +5124,16 @@ bfin_discard_copies (struct elf_link_has
+ }
+ 
+ static bool
+-bfin_size_dynamic_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
+-			    struct bfd_link_info *info)
++bfin_late_size_sections (bfd * output_bfd ATTRIBUTE_UNUSED,
++			 struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5423,8 +5425,7 @@ struct bfd_elf_special_section const elf
+ #define elf_backend_check_relocs	bfin_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 					bfin_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-					bfin_size_dynamic_sections
++#define elf_backend_late_size_sections	bfin_late_size_sections
+ #define elf_backend_relocate_section	bfin_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+ 					bfin_finish_dynamic_symbol
+@@ -5470,9 +5471,9 @@ struct bfd_elf_special_section const elf
+ #undef bfd_elf32_bfd_link_hash_table_create
+ #define bfd_elf32_bfd_link_hash_table_create \
+ 		bfinfdpic_elf_link_hash_table_create
+-#undef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections \
+-		elf32_bfinfdpic_always_size_sections
++#undef elf_backend_early_size_sections
++#define elf_backend_early_size_sections \
++		elf32_bfinfdpic_early_size_sections
+ 
+ #undef elf_backend_create_dynamic_sections
+ #define elf_backend_create_dynamic_sections \
+@@ -5480,9 +5481,9 @@ struct bfd_elf_special_section const elf
+ #undef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol \
+ 		elf32_bfinfdpic_adjust_dynamic_symbol
+-#undef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections \
+-		elf32_bfinfdpic_size_dynamic_sections
++#undef elf_backend_late_size_sections
++#define elf_backend_late_size_sections \
++		elf32_bfinfdpic_late_size_sections
+ #undef elf_backend_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol \
+ 		elf32_bfinfdpic_finish_dynamic_symbol
+--- a/bfd/elf32-cr16.c
++++ b/bfd/elf32-cr16.c
+@@ -2391,15 +2391,16 @@ _bfd_cr16_elf_adjust_dynamic_symbol (str
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-_bfd_cr16_elf_size_dynamic_sections (bfd * output_bfd,
+-				     struct bfd_link_info * info)
++_bfd_cr16_elf_late_size_sections (bfd * output_bfd,
++				  struct bfd_link_info * info)
+ {
+   bfd * dynobj;
+   asection * s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -2836,8 +2837,8 @@ _bfd_cr16_elf_reloc_type_class (const st
+ 				  _bfd_cr16_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol \
+ 				  _bfd_cr16_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-				  _bfd_cr16_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++				  _bfd_cr16_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_symbol \
+ 				   _bfd_cr16_elf_finish_dynamic_symbol
+--- a/bfd/elf32-cris.c
++++ b/bfd/elf32-cris.c
+@@ -2527,7 +2527,7 @@ cris_elf_plt_sym_val (bfd_vma i ATTRIBUT
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_cris_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_cris_size_dynamic_sections if no dynamic sections will be
++   or elf_cris_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static bool
+@@ -3508,8 +3508,8 @@ cris_elf_check_relocs (bfd *abfd,
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_cris_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_cris_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_cris_link_hash_table * htab;
+   bfd *dynobj;
+@@ -3521,7 +3521,8 @@ elf_cris_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -4090,8 +4091,8 @@ elf_cris_got_elt_size (bfd *abfd ATTRIBU
+ 	elf_cris_adjust_dynamic_symbol
+ #define elf_backend_copy_indirect_symbol \
+ 	elf_cris_copy_indirect_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elf_cris_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elf_cris_late_size_sections
+ #define elf_backend_init_index_section		_bfd_elf_init_1_index_section
+ #define elf_backend_finish_dynamic_symbol \
+ 	elf_cris_finish_dynamic_symbol
+--- a/bfd/elf32-csky.c
++++ b/bfd/elf32-csky.c
+@@ -1893,8 +1893,8 @@ csky_allocate_dynrelocs (struct elf_link
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-csky_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++csky_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct csky_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1907,7 +1907,7 @@ csky_elf_size_dynamic_sections (bfd *out
+     return false;
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    return false;
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -5333,7 +5333,7 @@ elf32_csky_obj_attrs_handle_unknown (bfd
+ /* Dynamic relocate related API.  */
+ #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol     csky_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections     csky_elf_size_dynamic_sections
++#define elf_backend_late_size_sections        csky_elf_late_size_sections
+ #define elf_backend_finish_dynamic_symbol     csky_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections   csky_elf_finish_dynamic_sections
+ #define elf_backend_rela_normal               1
+--- a/bfd/elf32-frv.c
++++ b/bfd/elf32-frv.c
+@@ -5423,15 +5423,16 @@ _frvfdpic_size_got_plt (bfd *output_bfd,
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_frvfdpic_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++elf32_frvfdpic_late_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   struct _frvfdpic_dynamic_got_plt_info gpinfo;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5472,8 +5473,8 @@ elf32_frvfdpic_size_dynamic_sections (bf
+ }
+ 
+ static bool
+-elf32_frvfdpic_always_size_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++elf32_frvfdpic_early_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info)
+       && !bfd_elf_stack_segment_size (output_bfd, info,
+@@ -6817,9 +6818,9 @@ elf32_frv_grok_psinfo (bfd *abfd, Elf_In
+ #undef bfd_elf32_bfd_link_hash_table_create
+ #define bfd_elf32_bfd_link_hash_table_create \
+ 		frvfdpic_elf_link_hash_table_create
+-#undef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections \
+-		elf32_frvfdpic_always_size_sections
++#undef elf_backend_early_size_sections
++#define elf_backend_early_size_sections \
++		elf32_frvfdpic_early_size_sections
+ 
+ #undef elf_backend_create_dynamic_sections
+ #define elf_backend_create_dynamic_sections \
+@@ -6827,9 +6828,9 @@ elf32_frv_grok_psinfo (bfd *abfd, Elf_In
+ #undef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol \
+ 		elf32_frvfdpic_adjust_dynamic_symbol
+-#undef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections \
+-		elf32_frvfdpic_size_dynamic_sections
++#undef elf_backend_late_size_sections
++#define elf_backend_late_size_sections \
++		elf32_frvfdpic_late_size_sections
+ #undef bfd_elf32_bfd_relax_section
+ #define bfd_elf32_bfd_relax_section \
+   elf32_frvfdpic_relax_section
+--- a/bfd/elf32-hppa.c
++++ b/bfd/elf32-hppa.c
+@@ -2042,8 +2042,8 @@ clobber_millicode_symbols (struct elf_li
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf32_hppa_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf32_hppa_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2057,7 +2057,7 @@ elf32_hppa_size_dynamic_sections (bfd *o
+ 
+   dynobj = htab->etab.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->etab.dynamic_sections_created)
+     {
+@@ -4452,7 +4452,7 @@ elf32_hppa_elf_get_symbol_type (Elf_Inte
+ #define elf_backend_hide_symbol		     elf32_hppa_hide_symbol
+ #define elf_backend_finish_dynamic_symbol    elf32_hppa_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  elf32_hppa_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections    elf32_hppa_size_dynamic_sections
++#define elf_backend_late_size_sections	     elf32_hppa_late_size_sections
+ #define elf_backend_init_index_section	     _bfd_elf_init_1_index_section
+ #define elf_backend_gc_mark_hook	     elf32_hppa_gc_mark_hook
+ #define elf_backend_grok_prstatus	     elf32_hppa_grok_prstatus
+--- a/bfd/elf32-i386.c
++++ b/bfd/elf32-i386.c
+@@ -1957,8 +1957,7 @@ elf_i386_scan_relocs (bfd *abfd,
+ }
+ 
+ static bool
+-elf_i386_always_size_sections (bfd *output_bfd,
+-			       struct bfd_link_info *info)
++elf_i386_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *abfd;
+ 
+@@ -1971,7 +1970,7 @@ elf_i386_always_size_sections (bfd *outp
+ 					     elf_i386_scan_relocs))
+       return false;
+ 
+-  return _bfd_x86_elf_always_size_sections (output_bfd, info);
++  return _bfd_x86_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ /* Set the correct type for an x86 ELF section.  We do this by the
+@@ -4479,7 +4478,7 @@ elf_i386_link_setup_gnu_properties (stru
+ #define bfd_elf32_get_synthetic_symtab	      elf_i386_get_synthetic_symtab
+ 
+ #define elf_backend_relocs_compatible	      _bfd_elf_relocs_compatible
+-#define elf_backend_always_size_sections      elf_i386_always_size_sections
++#define elf_backend_early_size_sections	      elf_i386_early_size_sections
+ #define elf_backend_create_dynamic_sections   _bfd_elf_create_dynamic_sections
+ #define elf_backend_fake_sections	      elf_i386_fake_sections
+ #define elf_backend_finish_dynamic_sections   elf_i386_finish_dynamic_sections
+--- a/bfd/elf32-lm32.c
++++ b/bfd/elf32-lm32.c
+@@ -1906,8 +1906,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-lm32_elf_size_dynamic_sections (bfd *output_bfd,
+-				struct bfd_link_info *info)
++lm32_elf_late_size_sections (bfd *output_bfd,
++			     struct bfd_link_info *info)
+ {
+   struct elf_lm32_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1920,7 +1920,8 @@ lm32_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -2309,7 +2310,7 @@ lm32_elf_create_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-lm32_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++lm32_elf_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (!bfd_link_relocatable (info))
+     {
+@@ -2395,7 +2396,7 @@ lm32_elf_fdpic_copy_private_bfd_data (bf
+ #define bfd_elf32_bfd_link_hash_table_create	lm32_elf_link_hash_table_create
+ #define elf_backend_check_relocs		lm32_elf_check_relocs
+ #define elf_backend_reloc_type_class		lm32_elf_reloc_type_class
+-#define elf_backend_size_dynamic_sections	lm32_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		lm32_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym		_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_create_dynamic_sections	lm32_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	lm32_elf_finish_dynamic_sections
+@@ -2416,8 +2417,8 @@ lm32_elf_fdpic_copy_private_bfd_data (bf
+ #undef	elf32_bed
+ #define	elf32_bed		elf32_lm32fdpic_bed
+ 
+-#undef	elf_backend_always_size_sections
+-#define elf_backend_always_size_sections	lm32_elf_always_size_sections
++#undef	elf_backend_early_size_sections
++#define elf_backend_early_size_sections		lm32_elf_early_size_sections
+ #undef	bfd_elf32_bfd_copy_private_bfd_data
+ #define bfd_elf32_bfd_copy_private_bfd_data	lm32_elf_fdpic_copy_private_bfd_data
+ 
+--- a/bfd/elf32-m32c.c
++++ b/bfd/elf32-m32c.c
+@@ -773,8 +773,8 @@ m32c_elf_finish_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-m32c_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++m32c_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -2132,8 +2132,8 @@ _bfd_m32c_elf_eh_frame_address_size (bfd
+ #define elf_backend_check_relocs		m32c_elf_check_relocs
+ #define elf_backend_object_p			m32c_elf_object_p
+ #define elf_symbol_leading_char			('_')
+-#define elf_backend_always_size_sections \
+-  m32c_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  m32c_elf_early_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   m32c_elf_finish_dynamic_sections
+ 
+--- a/bfd/elf32-m32r.c
++++ b/bfd/elf32-m32r.c
+@@ -1958,8 +1958,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-m32r_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++m32r_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1968,7 +1968,7 @@ m32r_elf_size_dynamic_sections (bfd *out
+   bfd *ibfd;
+ 
+ #ifdef DEBUG_PIC
+-  printf ("m32r_elf_size_dynamic_sections()\n");
++  printf ("m32r_elf_late_size_sections()\n");
+ #endif
+ 
+   htab = m32r_elf_hash_table (info);
+@@ -1976,7 +1976,8 @@ m32r_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->dynamic_sections_created)
+     {
+@@ -3658,7 +3659,7 @@ m32r_elf_reloc_type_class (const struct
+ 
+ #define elf_backend_create_dynamic_sections	m32r_elf_create_dynamic_sections
+ #define bfd_elf32_bfd_link_hash_table_create	m32r_elf_link_hash_table_create
+-#define elf_backend_size_dynamic_sections	m32r_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		m32r_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym		_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_sections	m32r_elf_finish_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol	m32r_elf_adjust_dynamic_symbol
+--- a/bfd/elf32-m68k.c
++++ b/bfd/elf32-m68k.c
+@@ -2934,7 +2934,7 @@ elf_m68k_get_plt_info (bfd *output_bfd)
+    It's a convenient place to determine the PLT style.  */
+ 
+ static bool
+-elf_m68k_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf_m68k_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   /* Bind input BFDs to GOTs and calculate sizes of .got and .rela.got
+      sections.  */
+@@ -3107,15 +3107,16 @@ elf_m68k_adjust_dynamic_symbol (struct b
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_m68k_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_m68k_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -4628,12 +4629,11 @@ elf_m68k_grok_psinfo (bfd *abfd, Elf_Int
+ #define bfd_elf32_bfd_final_link	bfd_elf_final_link
+ 
+ #define elf_backend_check_relocs	elf_m68k_check_relocs
+-#define elf_backend_always_size_sections \
+-					elf_m68k_always_size_sections
++#define elf_backend_early_size_sections \
++					elf_m68k_early_size_sections
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf_m68k_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-					elf_m68k_size_dynamic_sections
++#define elf_backend_late_size_sections	elf_m68k_late_size_sections
+ #define elf_backend_final_write_processing	elf_m68k_final_write_processing
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	elf_m68k_relocate_section
+--- a/bfd/elf32-metag.c
++++ b/bfd/elf32-metag.c
+@@ -2717,8 +2717,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_metag_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info *info)
++elf_metag_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   struct elf_metag_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2729,7 +2729,7 @@ elf_metag_size_dynamic_sections (bfd *ou
+   htab = metag_link_hash_table (info);
+   dynobj = htab->etab.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->etab.dynamic_sections_created)
+     {
+@@ -4019,7 +4019,7 @@ elf_metag_plt_sym_val (bfd_vma i, const
+ #define elf_backend_adjust_dynamic_symbol	elf_metag_adjust_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol	elf_metag_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	elf_metag_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	elf_metag_size_dynamic_sections
++#define elf_backend_late_size_sections		elf_metag_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_init_file_header		elf_metag_init_file_header
+--- a/bfd/elf32-microblaze.c
++++ b/bfd/elf32-microblaze.c
+@@ -2966,8 +2966,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-microblaze_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				      struct bfd_link_info *info)
++microblaze_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				   struct bfd_link_info *info)
+ {
+   struct elf32_mb_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2979,7 +2979,8 @@ microblaze_elf_size_dynamic_sections (bf
+     return false;
+ 
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   /* Set up .got offsets for local syms, and space for local dynamic
+      relocs.  */
+@@ -3497,7 +3498,7 @@ microblaze_elf_add_symbol_hook (bfd *abf
+ #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	microblaze_elf_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	microblaze_elf_finish_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	microblaze_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		microblaze_elf_late_size_sections
+ #define elf_backend_add_symbol_hook		microblaze_elf_add_symbol_hook
+ 
+ #include "elf32-target.h"
+--- a/bfd/elf32-mips.c
++++ b/bfd/elf32-mips.c
+@@ -2537,10 +2537,8 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf32-nds32.c
++++ b/bfd/elf32-nds32.c
+@@ -4302,8 +4302,8 @@ elf32_nds32_add_dynreloc (bfd *output_bf
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-nds32_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info *info)
++nds32_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   struct elf_nds32_link_hash_table *htab;
+   bfd *dynobj;
+@@ -4316,7 +4316,8 @@ nds32_elf_size_dynamic_sections (bfd *ou
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -13984,7 +13985,7 @@ nds32_elf_unify_tls_model (bfd *inbfd, a
+ #define elf_backend_create_dynamic_sections	nds32_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	nds32_elf_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol	nds32_elf_finish_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	nds32_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		nds32_elf_late_size_sections
+ #define elf_backend_relocate_section		nds32_elf_relocate_section
+ #define elf_backend_gc_mark_hook		nds32_elf_gc_mark_hook
+ #define elf_backend_grok_prstatus		nds32_elf_grok_prstatus
+--- a/bfd/elf32-nios2.c
++++ b/bfd/elf32-nios2.c
+@@ -5405,7 +5405,7 @@ nios2_elf32_adjust_dynamic_symbol (struc
+   return true;
+ }
+ 
+-/* Worker function for nios2_elf32_size_dynamic_sections.  */
++/* Worker function for nios2_elf32_late_size_sections.  */
+ static bool
+ adjust_dynrelocs (struct elf_link_hash_entry *h, void *inf)
+ {
+@@ -5432,7 +5432,7 @@ adjust_dynrelocs (struct elf_link_hash_e
+   return true;
+ }
+ 
+-/* Another worker function for nios2_elf32_size_dynamic_sections.
++/* Another worker function for nios2_elf32_late_size_sections.
+    Allocate space in .plt, .got and associated reloc sections for
+    dynamic relocs.  */
+ static bool
+@@ -5667,11 +5667,11 @@ allocate_dynrelocs (struct elf_link_hash
+   return true;
+ }
+ 
+-/* Implement elf_backend_size_dynamic_sections:
++/* Implement elf_backend_late_size_sections:
+    Set the sizes of the dynamic sections.  */
+ static bool
+-nios2_elf32_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				   struct bfd_link_info *info)
++nios2_elf32_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -5681,7 +5681,8 @@ nios2_elf32_size_dynamic_sections (bfd *
+ 
+   htab = elf32_nios2_hash_table (info);
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   htab->res_n_size = 0;
+   if (htab->root.dynamic_sections_created)
+@@ -6052,7 +6053,7 @@ const struct bfd_elf_special_section elf
+ 					  nios2_elf32_finish_dynamic_sections
+ #define elf_backend_adjust_dynamic_symbol nios2_elf32_adjust_dynamic_symbol
+ #define elf_backend_reloc_type_class	  nios2_elf32_reloc_type_class
+-#define elf_backend_size_dynamic_sections nios2_elf32_size_dynamic_sections
++#define elf_backend_late_size_sections	  nios2_elf32_late_size_sections
+ #define elf_backend_add_symbol_hook	  nios2_elf_add_symbol_hook
+ #define elf_backend_copy_indirect_symbol  nios2_elf32_copy_indirect_symbol
+ #define elf_backend_object_p		  nios2_elf32_object_p
+--- a/bfd/elf32-or1k.c
++++ b/bfd/elf32-or1k.c
+@@ -3047,8 +3047,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++or1k_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_or1k_link_hash_table *htab;
+   bfd *dynobj;
+@@ -3061,7 +3061,8 @@ or1k_elf_size_dynamic_sections (bfd *out
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -3414,7 +3415,7 @@ or1k_grok_psinfo (bfd *abfd, Elf_Interna
+ #define elf_backend_copy_indirect_symbol	or1k_elf_copy_indirect_symbol
+ #define elf_backend_create_dynamic_sections	_bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections	or1k_elf_finish_dynamic_sections
+-#define elf_backend_size_dynamic_sections	or1k_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		or1k_elf_late_size_sections
+ #define elf_backend_adjust_dynamic_symbol	or1k_elf_adjust_dynamic_symbol
+ #define elf_backend_finish_dynamic_symbol	or1k_elf_finish_dynamic_symbol
+ 
+--- a/bfd/elf32-ppc.c
++++ b/bfd/elf32-ppc.c
+@@ -5479,8 +5479,8 @@ static const unsigned char glink_eh_fram
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-ppc_elf_size_dynamic_sections (bfd *output_bfd,
+-			       struct bfd_link_info *info)
++ppc_elf_late_size_sections (bfd *output_bfd,
++			    struct bfd_link_info *info)
+ {
+   struct ppc_elf_link_hash_table *htab;
+   asection *s;
+@@ -5488,11 +5488,12 @@ ppc_elf_size_dynamic_sections (bfd *outp
+   bfd *ibfd;
+ 
+ #ifdef DEBUG
+-  fprintf (stderr, "ppc_elf_size_dynamic_sections called\n");
++  fprintf (stderr, "ppc_elf_late_size_sections called\n");
+ #endif
+ 
+   htab = ppc_elf_hash_table (info);
+-  BFD_ASSERT (htab->elf.dynobj != NULL);
++  if (htab->elf.dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -10433,7 +10434,7 @@ ppc_elf_finish_dynamic_sections (bfd *ou
+ #define elf_backend_copy_indirect_symbol	ppc_elf_copy_indirect_symbol
+ #define elf_backend_adjust_dynamic_symbol	ppc_elf_adjust_dynamic_symbol
+ #define elf_backend_add_symbol_hook		ppc_elf_add_symbol_hook
+-#define elf_backend_size_dynamic_sections	ppc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		ppc_elf_late_size_sections
+ #define elf_backend_hash_symbol			ppc_elf_hash_symbol
+ #define elf_backend_finish_dynamic_symbol	ppc_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	ppc_elf_finish_dynamic_sections
+--- a/bfd/elf32-rl78.c
++++ b/bfd/elf32-rl78.c
+@@ -1440,8 +1440,8 @@ rl78_elf_finish_dynamic_sections (bfd *a
+ }
+ 
+ static bool
+-rl78_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			       struct bfd_link_info *info)
++rl78_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -2610,8 +2610,8 @@ rl78_elf_relax_section (bfd *abfd,
+ 
+ #define bfd_elf32_bfd_relax_section		rl78_elf_relax_section
+ #define elf_backend_check_relocs		rl78_elf_check_relocs
+-#define elf_backend_always_size_sections \
+-  rl78_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  rl78_elf_early_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   rl78_elf_finish_dynamic_sections
+ 
+--- a/bfd/elf32-s390.c
++++ b/bfd/elf32-s390.c
+@@ -1366,7 +1366,7 @@ elf_s390_gc_mark_hook (asection *sec,
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_s390_size_dynamic_sections if no dynamic sections will be
++   or elf_s390_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static void
+@@ -1778,8 +1778,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_s390_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1790,7 +1790,7 @@ elf_s390_size_dynamic_sections (bfd *out
+   htab = elf_s390_hash_table (info);
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3926,7 +3926,7 @@ elf32_s390_merge_private_bfd_data (bfd *
+ #define elf_backend_gc_mark_hook	      elf_s390_gc_mark_hook
+ #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
+ #define elf_backend_relocate_section	      elf_s390_relocate_section
+-#define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
++#define elf_backend_late_size_sections	      elf_s390_late_size_sections
+ #define elf_backend_init_index_section	      _bfd_elf_init_1_index_section
+ #define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
+ #define elf_backend_grok_psinfo		      elf_s390_grok_psinfo
+--- a/bfd/elf32-score.c
++++ b/bfd/elf32-score.c
+@@ -1089,7 +1089,7 @@ score_elf_got_info (bfd *abfd, asection
+    appear towards the end.  This reduces the amount of GOT space
+    required.  MAX_LOCAL is used to set the number of local symbols
+    known to be in the dynamic symbol table.  During
+-   s3_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
++   s3_bfd_score_elf_late_size_sections, this value is 1.  Afterward, the
+    section symbols are added and the count is higher.  */
+ static bool
+ score_elf_sort_hash_table (struct bfd_link_info *info,
+@@ -3160,8 +3160,8 @@ s3_bfd_score_elf_adjust_dynamic_symbol (
+ /* This function is called after all the input files have been read,
+    and the input sections have been assigned to output sections.  */
+ static bool
+-s3_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				       struct bfd_link_info *info)
++s3_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -3237,14 +3237,15 @@ s3_bfd_score_elf_always_size_sections (b
+ 
+ /* Set the sizes of the dynamic sections.  */
+ static bool
+-s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++s3_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool reltext;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3313,7 +3314,7 @@ s3_bfd_score_elf_size_dynamic_sections (
+ 	}
+       else if (startswith (name, ".got"))
+ 	{
+-	  /* s3_bfd_score_elf_always_size_sections() has already done
++	  /* s3_bfd_score_elf_early_size_sections() has already done
+ 	     most of the work, but some symbols may have been mapped
+ 	     to versions that we must now resolve in the got_entries
+ 	     hash tables.  */
+@@ -4177,22 +4178,22 @@ _bfd_score_elf_adjust_dynamic_symbol (st
+ }
+ 
+ static bool
+-_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				    struct bfd_link_info *info)
+ {
+   if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+-    return s3_bfd_score_elf_always_size_sections (output_bfd, info);
++    return s3_bfd_score_elf_early_size_sections (output_bfd, info);
+   else
+-    return s7_bfd_score_elf_always_size_sections (output_bfd, info);
++    return s7_bfd_score_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ static bool
+-_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (bfd_get_mach (output_bfd) == bfd_mach_score3)
+-    return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info);
++    return s3_bfd_score_elf_late_size_sections (output_bfd, info);
+   else
+-    return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info);
++    return s7_bfd_score_elf_late_size_sections (output_bfd, info);
+ }
+ 
+ static bool
+@@ -4455,10 +4456,10 @@ _bfd_score_elf_common_definition (Elf_In
+   _bfd_score_elf_section_from_bfd_section
+ #define elf_backend_adjust_dynamic_symbol \
+   _bfd_score_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-  _bfd_score_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_score_elf_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  _bfd_score_elf_early_size_sections
++#define elf_backend_late_size_sections \
++  _bfd_score_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_create_dynamic_sections \
+   _bfd_score_elf_create_dynamic_sections
+--- a/bfd/elf32-score.h
++++ b/bfd/elf32-score.h
+@@ -78,10 +78,10 @@ s7_bfd_score_elf_adjust_dynamic_symbol (
+ 					struct elf_link_hash_entry *);
+ 
+ extern bool
+-s7_bfd_score_elf_always_size_sections (bfd *, struct bfd_link_info *);
++s7_bfd_score_elf_early_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern bool
+-s7_bfd_score_elf_size_dynamic_sections (bfd *, struct bfd_link_info *);
++s7_bfd_score_elf_late_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern bool
+ s7_bfd_score_elf_create_dynamic_sections (bfd *, struct bfd_link_info *);
+--- a/bfd/elf32-score7.c
++++ b/bfd/elf32-score7.c
+@@ -975,7 +975,7 @@ score_elf_got_info (bfd *abfd, asection
+    appear towards the end.  This reduces the amount of GOT space
+    required.  MAX_LOCAL is used to set the number of local symbols
+    known to be in the dynamic symbol table.  During
+-   s7_bfd_score_elf_size_dynamic_sections, this value is 1.  Afterward, the
++   s7_bfd_score_elf_late_size_sections, this value is 1.  Afterward, the
+    section symbols are added and the count is higher.  */
+ 
+ static bool
+@@ -2969,8 +2969,8 @@ s7_bfd_score_elf_adjust_dynamic_symbol (
+    and the input sections have been assigned to output sections.  */
+ 
+ bool
+-s7_bfd_score_elf_always_size_sections (bfd *output_bfd,
+-				       struct bfd_link_info *info)
++s7_bfd_score_elf_early_size_sections (bfd *output_bfd,
++				      struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -3047,14 +3047,15 @@ s7_bfd_score_elf_always_size_sections (b
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-s7_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++s7_bfd_score_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool reltext;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3123,7 +3124,7 @@ s7_bfd_score_elf_size_dynamic_sections (
+ 	}
+       else if (startswith (name, ".got"))
+ 	{
+-	  /* s7_bfd_score_elf_always_size_sections() has already done
++	  /* s7_bfd_score_elf_early_size_sections() has already done
+ 	     most of the work, but some symbols may have been mapped
+ 	     to versions that we must now resolve in the got_entries
+ 	     hash tables.  */
+--- a/bfd/elf32-sh.c
++++ b/bfd/elf32-sh.c
+@@ -2927,7 +2927,7 @@ allocate_dynrelocs (struct elf_link_hash
+    It's a convenient place to determine the PLT style.  */
+ 
+ static bool
+-sh_elf_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++sh_elf_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   sh_elf_hash_table (info)->plt_info = get_plt_info (output_bfd,
+ 						     bfd_link_pic (info));
+@@ -2942,8 +2942,8 @@ sh_elf_always_size_sections (bfd *output
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-sh_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			      struct bfd_link_info *info)
++sh_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			   struct bfd_link_info *info)
+ {
+   struct elf_sh_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2956,7 +2956,8 @@ sh_elf_size_dynamic_sections (bfd *outpu
+     return false;
+ 
+   dynobj = htab->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -6600,10 +6601,8 @@ sh_elf_encode_eh_address (bfd *abfd,
+ 					sh_elf_link_hash_table_create
+ #define elf_backend_adjust_dynamic_symbol \
+ 					sh_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					sh_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					sh_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	sh_elf_early_size_sections
++#define elf_backend_late_size_sections	sh_elf_late_size_sections
+ #define elf_backend_omit_section_dynsym	sh_elf_omit_section_dynsym
+ #define elf_backend_finish_dynamic_symbol \
+ 					sh_elf_finish_dynamic_symbol
+--- a/bfd/elf32-sparc.c
++++ b/bfd/elf32-sparc.c
+@@ -248,8 +248,7 @@ elf32_sparc_reloc_type_class (const stru
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_sparc_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	_bfd_sparc_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_sparc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	_bfd_sparc_elf_late_size_sections
+ #define elf_backend_relocate_section	_bfd_sparc_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+ 					_bfd_sparc_elf_finish_dynamic_symbol
+--- a/bfd/elf32-tic6x.c
++++ b/bfd/elf32-tic6x.c
+@@ -3160,7 +3160,7 @@ elf32_tic6x_allocate_dynrelocs (struct e
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf32_tic6x_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf32_tic6x_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf32_tic6x_link_hash_table *htab;
+   bfd *dynobj;
+@@ -3171,7 +3171,7 @@ elf32_tic6x_size_dynamic_sections (bfd *
+   htab = elf32_tic6x_hash_table (info);
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3358,7 +3358,7 @@ elf32_tic6x_size_dynamic_sections (bfd *
+    and the input sections have been assigned to output sections.  */
+ 
+ static bool
+-elf32_tic6x_always_size_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf32_tic6x_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   if (elf32_tic6x_using_dsbt (output_bfd) && !bfd_link_relocatable (info)
+       && !bfd_elf_stack_segment_size (output_bfd, info,
+@@ -4261,10 +4261,10 @@ elf32_tic6x_write_section (bfd *output_b
+ #define elf_backend_relocs_compatible	_bfd_elf_relocs_compatible
+ #define elf_backend_finish_dynamic_symbol \
+   elf32_tic6x_finish_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-  elf32_tic6x_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  elf32_tic6x_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  elf32_tic6x_early_size_sections
++#define elf_backend_late_size_sections \
++  elf32_tic6x_late_size_sections
+ #define elf_backend_finish_dynamic_sections \
+   elf32_tic6x_finish_dynamic_sections
+ #define bfd_elf32_bfd_final_link \
+--- a/bfd/elf32-tilegx.c
++++ b/bfd/elf32-tilegx.c
+@@ -105,7 +105,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_I
+ #define elf_backend_check_relocs	     tilegx_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilegx_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilegx_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilegx_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilegx_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilegx_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilegx_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilegx_elf_finish_dynamic_sections
+--- a/bfd/elf32-tilepro.c
++++ b/bfd/elf32-tilepro.c
+@@ -2182,11 +2182,9 @@ tilepro_elf_omit_section_dynsym (bfd *ou
+ #define ELF32_DYNAMIC_INTERPRETER "/lib/ld.so.1"
+ 
+ static bool
+-tilepro_elf_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++tilepro_elf_late_size_sections (bfd *output_bfd,
++				struct bfd_link_info *info)
+ {
+-  (void)output_bfd;
+-
+   struct elf_link_hash_table *htab;
+   bfd *dynobj;
+   asection *s;
+@@ -2195,7 +2193,8 @@ tilepro_elf_size_dynamic_sections (bfd *
+   htab = tilepro_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -3739,7 +3738,7 @@ tilepro_additional_program_headers (bfd
+ #define elf_backend_check_relocs	     tilepro_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilepro_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilepro_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilepro_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilepro_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilepro_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilepro_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilepro_elf_finish_dynamic_sections
+--- a/bfd/elf32-vax.c
++++ b/bfd/elf32-vax.c
+@@ -36,7 +36,6 @@ static bool elf_vax_check_relocs (bfd *,
+ 				  asection *, const Elf_Internal_Rela *);
+ static bool elf_vax_adjust_dynamic_symbol (struct bfd_link_info *,
+ 					   struct elf_link_hash_entry *);
+-static bool elf_vax_size_dynamic_sections (bfd *, struct bfd_link_info *);
+ static int elf_vax_relocate_section (bfd *, struct bfd_link_info *,
+ 				     bfd *, asection *, bfd_byte *,
+ 				     Elf_Internal_Rela *,
+@@ -985,8 +984,8 @@ elf_vax_discard_got_entries (struct elf_
+ /* Discard unused dynamic data if this is a static link.  */
+ 
+ static bool
+-elf_vax_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-			      struct bfd_link_info *info)
++elf_vax_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -1024,14 +1023,15 @@ elf_vax_always_size_sections (bfd *outpu
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_vax_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf_vax_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+   bool relocs;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -1861,10 +1861,8 @@ elf_vax_plt_sym_val (bfd_vma i, const as
+ #define elf_backend_check_relocs	elf_vax_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf_vax_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					elf_vax_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					elf_vax_size_dynamic_sections
++#define elf_backend_early_size_sections	elf_vax_early_size_sections
++#define elf_backend_late_size_sections	elf_vax_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	elf_vax_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf32-xstormy16.c
++++ b/bfd/elf32-xstormy16.c
+@@ -706,8 +706,8 @@ xstormy16_elf_relax_section (bfd *dynobj
+ }
+ 
+ static bool
+-xstormy16_elf_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				    struct bfd_link_info *info)
++xstormy16_elf_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				   struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *splt;
+@@ -1013,8 +1013,8 @@ xstormy16_elf_gc_mark_hook (asection *se
+ #define elf_backend_relocate_section		xstormy16_elf_relocate_section
+ #define elf_backend_gc_mark_hook		xstormy16_elf_gc_mark_hook
+ #define elf_backend_check_relocs		xstormy16_elf_check_relocs
+-#define elf_backend_always_size_sections \
+-  xstormy16_elf_always_size_sections
++#define elf_backend_early_size_sections \
++  xstormy16_elf_early_size_sections
+ #define elf_backend_omit_section_dynsym \
+   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_finish_dynamic_sections \
+--- a/bfd/elf32-xtensa.c
++++ b/bfd/elf32-xtensa.c
+@@ -1557,8 +1557,8 @@ elf_xtensa_allocate_local_got_size (stru
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_xtensa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf_xtensa_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf_xtensa_link_hash_table *htab;
+   bfd *dynobj, *abfd;
+@@ -1575,7 +1575,7 @@ elf_xtensa_size_dynamic_sections (bfd *o
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+   srelgot = htab->elf.srelgot;
+   srelplt = htab->elf.srelplt;
+ 
+@@ -1780,8 +1780,7 @@ elf_xtensa_size_dynamic_sections (bfd *o
+ }
+ 
+ static bool
+-elf_xtensa_always_size_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++elf_xtensa_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf_xtensa_link_hash_table *htab;
+   asection *tls_sec;
+@@ -11544,8 +11543,8 @@ static const struct bfd_elf_special_sect
+ #define elf_backend_object_p		     elf_xtensa_object_p
+ #define elf_backend_reloc_type_class	     elf_xtensa_reloc_type_class
+ #define elf_backend_relocate_section	     elf_xtensa_relocate_section
+-#define elf_backend_size_dynamic_sections    elf_xtensa_size_dynamic_sections
+-#define elf_backend_always_size_sections     elf_xtensa_always_size_sections
++#define elf_backend_late_size_sections	     elf_xtensa_late_size_sections
++#define elf_backend_early_size_sections	     elf_xtensa_early_size_sections
+ #define elf_backend_omit_section_dynsym      _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_special_sections	     elf_xtensa_special_sections
+ #define elf_backend_action_discarded	     elf_xtensa_action_discarded
+--- a/bfd/elf64-alpha.c
++++ b/bfd/elf64-alpha.c
+@@ -2562,8 +2562,8 @@ elf64_alpha_size_plt_section (struct bfd
+ }
+ 
+ static bool
+-elf64_alpha_always_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf64_alpha_early_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				 struct bfd_link_info *info)
+ {
+   bfd *i;
+   struct alpha_elf_link_hash_table * htab;
+@@ -2789,8 +2789,8 @@ elf64_alpha_size_rela_got_section (struc
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf64_alpha_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				   struct bfd_link_info *info)
++elf64_alpha_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s;
+@@ -2802,7 +2802,8 @@ elf64_alpha_size_dynamic_sections (bfd *
+     return false;
+ 
+   dynobj = elf_hash_table(info)->dynobj;
+-  BFD_ASSERT(dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5448,10 +5449,10 @@ static const struct elf_size_info alpha_
+   elf64_alpha_merge_symbol_attribute
+ #define elf_backend_copy_indirect_symbol \
+   elf64_alpha_copy_indirect_symbol
+-#define elf_backend_always_size_sections \
+-  elf64_alpha_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-  elf64_alpha_size_dynamic_sections
++#define elf_backend_early_size_sections \
++  elf64_alpha_early_size_sections
++#define elf_backend_late_size_sections \
++  elf64_alpha_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+   _bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elf64-hppa.c
++++ b/bfd/elf64-hppa.c
+@@ -176,9 +176,6 @@ static bool elf64_hppa_adjust_dynamic_sy
+ static bool elf64_hppa_mark_milli_and_exported_functions
+   (struct elf_link_hash_entry *, void *);
+ 
+-static bool elf64_hppa_size_dynamic_sections
+-  (bfd *, struct bfd_link_info *);
+-
+ static int elf64_hppa_link_output_symbol_hook
+   (struct bfd_link_info *, const char *, Elf_Internal_Sym *,
+    asection *, struct elf_link_hash_entry *);
+@@ -1520,7 +1517,7 @@ elf64_hppa_mark_milli_and_exported_funct
+    the contents of our special sections.  */
+ 
+ static bool
+-elf64_hppa_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct elf64_hppa_link_hash_table *hppa_info;
+   struct elf64_hppa_allocate_data data;
+@@ -1534,7 +1531,8 @@ elf64_hppa_size_dynamic_sections (bfd *o
+     return false;
+ 
+   dynobj = hppa_info->root.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   /* Mark each function this program exports so that we will allocate
+      space in the .opd section for each function's FPTR.  If we are
+@@ -3984,8 +3982,7 @@ const struct elf_size_info hppa64_elf_si
+ #define elf_backend_adjust_dynamic_symbol \
+ 					elf64_hppa_adjust_dynamic_symbol
+ 
+-#define elf_backend_size_dynamic_sections \
+-					elf64_hppa_size_dynamic_sections
++#define elf_backend_late_size_sections	elf64_hppa_late_size_sections
+ 
+ #define elf_backend_finish_dynamic_symbol \
+ 					elf64_hppa_finish_dynamic_symbol
+--- a/bfd/elf64-ia64-vms.c
++++ b/bfd/elf64-ia64-vms.c
+@@ -2591,8 +2591,8 @@ elf64_ia64_adjust_dynamic_symbol (struct
+ }
+ 
+ static bool
+-elf64_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elf64_ia64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elf64_ia64_allocate_data data;
+   struct elf64_ia64_link_hash_table *ia64_info;
+@@ -2601,11 +2601,12 @@ elf64_ia64_size_dynamic_sections (bfd *o
+   struct elf_link_hash_table *hash_table;
+ 
+   hash_table = elf_hash_table (info);
+-  dynobj = hash_table->dynobj;
+   ia64_info = elf64_ia64_hash_table (info);
+   if (ia64_info == NULL)
+     return false;
+-  BFD_ASSERT(dynobj != NULL);
++  dynobj = hash_table->dynobj;
++  if (dynobj == NULL)
++    return true;
+   data.info = info;
+ 
+   /* Allocate the GOT entries.  */
+@@ -5488,8 +5489,8 @@ static const struct elf_size_info elf64_
+ 	elf64_ia64_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 	elf64_ia64_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elf64_ia64_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elf64_ia64_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elf64-mips.c
++++ b/bfd/elf64-mips.c
+@@ -4748,10 +4748,10 @@ const struct elf_size_info mips_elf64_si
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 				_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-				_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-				_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections \
++				_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections \
++				_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section    _bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf64-ppc.c
++++ b/bfd/elf64-ppc.c
+@@ -119,8 +119,8 @@ static bfd_vma opd_entry_value
+ #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
+ #define elf_backend_hide_symbol		      ppc64_elf_hide_symbol
+ #define elf_backend_maybe_function_sym	      ppc64_elf_maybe_function_sym
+-#define elf_backend_always_size_sections      ppc64_elf_edit
+-#define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	      ppc64_elf_edit
++#define elf_backend_late_size_sections	      ppc64_elf_late_size_sections
+ #define elf_backend_hash_symbol		      ppc64_elf_hash_symbol
+ #define elf_backend_init_index_section	      _bfd_elf_init_2_index_sections
+ #define elf_backend_action_discarded	      ppc64_elf_action_discarded
+@@ -10148,7 +10148,7 @@ allocate_dynrelocs (struct elf_link_hash
+   ((((v) & 0x3ffff0000ULL) << 16) | (v & 0xffff))
+ #define HA34(v) ((v + (1ULL << 33)) >> 34)
+ 
+-/* Called via elf_link_hash_traverse from ppc64_elf_size_dynamic_sections
++/* Called via elf_link_hash_traverse from ppc64_elf_late_size_sections
+    to set up space for global entry stubs.  These are put in glink,
+    after the branch table.  */
+ 
+@@ -10225,8 +10225,8 @@ size_global_entry_stubs (struct elf_link
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-ppc64_elf_size_dynamic_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++ppc64_elf_late_size_sections (bfd *output_bfd,
++			      struct bfd_link_info *info)
+ {
+   struct ppc_link_hash_table *htab;
+   bfd *dynobj;
+@@ -10241,7 +10241,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
+ 
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+--- a/bfd/elf64-s390.c
++++ b/bfd/elf64-s390.c
+@@ -1301,7 +1301,7 @@ elf_s390_gc_mark_hook (asection *sec,
+    entry but we found we will not create any.  Called when we find we will
+    not have any PLT for this symbol, by for example
+    elf_s390_adjust_dynamic_symbol when we're doing a proper dynamic link,
+-   or elf_s390_size_dynamic_sections if no dynamic sections will be
++   or elf_s390_late_size_sections if no dynamic sections will be
+    created (we're only linking static objects).  */
+ 
+ static void
+@@ -1714,8 +1714,8 @@ allocate_dynrelocs (struct elf_link_hash
+ /* Set the sizes of the dynamic sections.  */
+ 
+ static bool
+-elf_s390_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				struct bfd_link_info *info)
++elf_s390_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			     struct bfd_link_info *info)
+ {
+   struct elf_s390_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1729,7 +1729,7 @@ elf_s390_size_dynamic_sections (bfd *out
+ 
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -3912,7 +3912,7 @@ const struct elf_size_info s390_elf64_si
+ #define elf_backend_gc_mark_hook	      elf_s390_gc_mark_hook
+ #define elf_backend_reloc_type_class	      elf_s390_reloc_type_class
+ #define elf_backend_relocate_section	      elf_s390_relocate_section
+-#define elf_backend_size_dynamic_sections     elf_s390_size_dynamic_sections
++#define elf_backend_late_size_sections	      elf_s390_late_size_sections
+ #define elf_backend_init_index_section	      _bfd_elf_init_1_index_section
+ #define elf_backend_grok_prstatus	      elf_s390_grok_prstatus
+ #define elf_backend_grok_psinfo		      elf_s390_grok_psinfo
+--- a/bfd/elf64-sparc.c
++++ b/bfd/elf64-sparc.c
+@@ -953,8 +953,8 @@ const struct elf_size_info elf64_sparc_s
+   _bfd_sparc_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym \
+   _bfd_sparc_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_sparc_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_sparc_elf_late_size_sections
+ #define elf_backend_relocate_section \
+   _bfd_sparc_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elf64-tilegx.c
++++ b/bfd/elf64-tilegx.c
+@@ -106,7 +106,7 @@ tilegx_elf_grok_psinfo (bfd *abfd, Elf_I
+ #define elf_backend_check_relocs	     tilegx_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol    tilegx_elf_adjust_dynamic_symbol
+ #define elf_backend_omit_section_dynsym	     tilegx_elf_omit_section_dynsym
+-#define elf_backend_size_dynamic_sections    tilegx_elf_size_dynamic_sections
++#define elf_backend_late_size_sections	     tilegx_elf_late_size_sections
+ #define elf_backend_relocate_section	     tilegx_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol    tilegx_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections  tilegx_elf_finish_dynamic_sections
+--- a/bfd/elf64-x86-64.c
++++ b/bfd/elf64-x86-64.c
+@@ -2549,8 +2549,7 @@ elf_x86_64_scan_relocs (bfd *abfd, struc
+ }
+ 
+ static bool
+-elf_x86_64_always_size_sections (bfd *output_bfd,
+-				 struct bfd_link_info *info)
++elf_x86_64_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   bfd *abfd;
+ 
+@@ -2563,7 +2562,7 @@ elf_x86_64_always_size_sections (bfd *ou
+ 					     elf_x86_64_scan_relocs))
+       return false;
+ 
+-  return _bfd_x86_elf_always_size_sections (output_bfd, info);
++  return _bfd_x86_elf_early_size_sections (output_bfd, info);
+ }
+ 
+ /* Return the relocation value for @tpoff relocation
+@@ -5638,7 +5637,7 @@ elf_x86_64_special_sections[]=
+   elf_x86_64_reloc_name_lookup
+ 
+ #define elf_backend_relocs_compatible	    elf_x86_64_relocs_compatible
+-#define elf_backend_always_size_sections    elf_x86_64_always_size_sections
++#define elf_backend_early_size_sections	    elf_x86_64_early_size_sections
+ #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
+ #define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
+ #define elf_backend_finish_dynamic_symbol   elf_x86_64_finish_dynamic_symbol
+--- a/bfd/elflink.c
++++ b/bfd/elflink.c
+@@ -6676,8 +6676,8 @@ bfd_elf_size_dynamic_sections (bfd *outp
+ 
+   /* The backend may have to create some sections regardless of whether
+      we're dynamic or not.  */
+-  if (bed->elf_backend_always_size_sections
+-      && ! (*bed->elf_backend_always_size_sections) (output_bfd, info))
++  if (bed->elf_backend_early_size_sections
++      && !bed->elf_backend_early_size_sections (output_bfd, info))
+     return false;
+ 
+   dynobj = elf_hash_table (info)->dynobj;
+@@ -7483,9 +7483,8 @@ NOTE: This behaviour is deprecated and w
+ 
+   /* The backend must work out the sizes of all the other dynamic
+      sections.  */
+-  if (dynobj != NULL
+-      && bed->elf_backend_size_dynamic_sections != NULL
+-      && ! (*bed->elf_backend_size_dynamic_sections) (output_bfd, info))
++  if (bed->elf_backend_late_size_sections != NULL
++      && !bed->elf_backend_late_size_sections (output_bfd, info))
+     return false;
+ 
+   if (dynobj != NULL && elf_hash_table (info)->dynamic_sections_created)
+--- a/bfd/elfn32-mips.c
++++ b/bfd/elfn32-mips.c
+@@ -4138,10 +4138,8 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_always_size_sections \
+-					_bfd_mips_elf_always_size_sections
+-#define elf_backend_size_dynamic_sections \
+-					_bfd_mips_elf_size_dynamic_sections
++#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
++#define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol \
+--- a/bfd/elfnn-aarch64.c
++++ b/bfd/elfnn-aarch64.c
+@@ -112,7 +112,7 @@
+   allocate space for one relocation on the slot. Record the GOT offset
+   for this symbol.
+ 
+-  elfNN_aarch64_size_dynamic_sections ()
++  elfNN_aarch64_late_size_sections ()
+ 
+   Iterate all input BFDS, look for in the local symbol data structure
+   constructed earlier for local TLS symbols and allocate them double
+@@ -9175,8 +9175,8 @@ elfNN_aarch64_allocate_local_ifunc_dynre
+    though !  */
+ 
+ static bool
+-elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				     struct bfd_link_info *info)
++elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++				  struct bfd_link_info *info)
+ {
+   struct elf_aarch64_link_hash_table *htab;
+   bfd *dynobj;
+@@ -9187,7 +9187,8 @@ elfNN_aarch64_size_dynamic_sections (bfd
+   htab = elf_aarch64_hash_table ((info));
+   dynobj = htab->root.dynobj;
+ 
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -9589,8 +9590,8 @@ elfNN_aarch64_create_small_pltn_entry (s
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bool
+-elfNN_aarch64_always_size_sections (bfd *output_bfd,
+-				    struct bfd_link_info *info)
++elfNN_aarch64_early_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+ 
+@@ -10323,8 +10324,8 @@ const struct elf_size_info elfNN_aarch64
+ #define elf_backend_adjust_dynamic_symbol	\
+   elfNN_aarch64_adjust_dynamic_symbol
+ 
+-#define elf_backend_always_size_sections	\
+-  elfNN_aarch64_always_size_sections
++#define elf_backend_early_size_sections		\
++  elfNN_aarch64_early_size_sections
+ 
+ #define elf_backend_check_relocs		\
+   elfNN_aarch64_check_relocs
+@@ -10379,8 +10380,8 @@ const struct elf_size_info elfNN_aarch64
+ #define elf_backend_modify_headers		\
+   elfNN_aarch64_modify_headers
+ 
+-#define elf_backend_size_dynamic_sections	\
+-  elfNN_aarch64_size_dynamic_sections
++#define elf_backend_late_size_sections		\
++  elfNN_aarch64_late_size_sections
+ 
+ #define elf_backend_size_info			\
+   elfNN_aarch64_size_info
+--- a/bfd/elfnn-ia64.c
++++ b/bfd/elfnn-ia64.c
+@@ -2987,8 +2987,8 @@ elfNN_ia64_adjust_dynamic_symbol (struct
+ }
+ 
+ static bool
+-elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++elfNN_ia64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct elfNN_ia64_allocate_data data;
+   struct elfNN_ia64_link_hash_table *ia64_info;
+@@ -2999,8 +2999,9 @@ elfNN_ia64_size_dynamic_sections (bfd *o
+   if (ia64_info == NULL)
+     return false;
+   dynobj = ia64_info->root.dynobj;
++  if (dynobj == NULL)
++    return true;
+   ia64_info->self_dtpmod_offset = (bfd_vma) -1;
+-  BFD_ASSERT(dynobj != NULL);
+   data.info = info;
+ 
+   /* Set the contents of the .interp section to the interpreter.  */
+@@ -5036,8 +5037,8 @@ ignore_errors (const char *fmt ATTRIBUTE
+ 	elfNN_ia64_check_relocs
+ #define elf_backend_adjust_dynamic_symbol \
+ 	elfNN_ia64_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections \
+-	elfNN_ia64_size_dynamic_sections
++#define elf_backend_late_size_sections \
++	elfNN_ia64_late_size_sections
+ #define elf_backend_omit_section_dynsym \
+ 	_bfd_elf_omit_section_dynsym_all
+ #define elf_backend_relocate_section \
+--- a/bfd/elfnn-kvx.c
++++ b/bfd/elfnn-kvx.c
+@@ -4033,8 +4033,8 @@ kvx_readonly_dynrelocs (struct elf_link_
+ /* This is the most important function of all . Innocuosly named
+    though !  */
+ static bool
+-elfNN_kvx_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				 struct bfd_link_info *info)
++elfNN_kvx_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			      struct bfd_link_info *info)
+ {
+   struct elf_kvx_link_hash_table *htab;
+   bfd *dynobj;
+@@ -4044,8 +4044,8 @@ elfNN_kvx_size_dynamic_sections (bfd *ou
+ 
+   htab = elf_kvx_hash_table ((info));
+   dynobj = htab->root.dynobj;
+-
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->root.dynamic_sections_created)
+     {
+@@ -4359,8 +4359,7 @@ elfNN_kvx_create_small_pltn_entry (struc
+    _TLS_MODULE_BASE_, if needed.  */
+ 
+ static bool
+-elfNN_kvx_always_size_sections (bfd *output_bfd,
+-				struct bfd_link_info *info)
++elfNN_kvx_early_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   asection *tls_sec;
+ 
+@@ -4715,8 +4714,8 @@ elfNN_kvx_plt_sym_val (bfd_vma i, const
+ #define elf_backend_adjust_dynamic_symbol	\
+   elfNN_kvx_adjust_dynamic_symbol
+ 
+-#define elf_backend_always_size_sections	\
+-  elfNN_kvx_always_size_sections
++#define elf_backend_early_size_sections		\
++  elfNN_kvx_early_size_sections
+ 
+ #define elf_backend_check_relocs		\
+   elfNN_kvx_check_relocs
+@@ -4759,8 +4758,8 @@ elfNN_kvx_plt_sym_val (bfd_vma i, const
+ #define elf_backend_reloc_type_class		\
+   elfNN_kvx_reloc_type_class
+ 
+-#define elf_backend_size_dynamic_sections	\
+-  elfNN_kvx_size_dynamic_sections
++#define elf_backend_late_size_sections	\
++  elfNN_kvx_late_size_sections
+ 
+ #define elf_backend_can_refcount       1
+ #define elf_backend_can_gc_sections    1
+--- a/bfd/elfnn-loongarch.c
++++ b/bfd/elfnn-loongarch.c
+@@ -1731,8 +1731,8 @@ maybe_set_textrel (struct elf_link_hash_
+ }
+ 
+ static bool
+-loongarch_elf_size_dynamic_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++loongarch_elf_late_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   struct loongarch_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1742,7 +1742,8 @@ loongarch_elf_size_dynamic_sections (bfd
+   htab = loongarch_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (htab->elf.dynamic_sections_created)
+     {
+@@ -5340,7 +5341,7 @@ elf_loongarch64_hash_symbol (struct elf_
+   loongarch_elf_create_dynamic_sections
+ #define elf_backend_check_relocs loongarch_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol loongarch_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections loongarch_elf_size_dynamic_sections
++#define elf_backend_late_size_sections loongarch_elf_late_size_sections
+ #define elf_backend_relocate_section loongarch_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol loongarch_elf_finish_dynamic_symbol
+ #define elf_backend_output_arch_local_syms \
+--- a/bfd/elfnn-riscv.c
++++ b/bfd/elfnn-riscv.c
+@@ -1482,7 +1482,7 @@ allocate_local_ifunc_dynrelocs (void **s
+ }
+ 
+ static bool
+-riscv_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
++riscv_elf_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
+ {
+   struct riscv_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -1492,7 +1492,8 @@ riscv_elf_size_dynamic_sections (bfd *ou
+   htab = riscv_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -5570,7 +5571,7 @@ riscv_elf_merge_symbol_attribute (struct
+ #define elf_backend_create_dynamic_sections	riscv_elf_create_dynamic_sections
+ #define elf_backend_check_relocs		riscv_elf_check_relocs
+ #define elf_backend_adjust_dynamic_symbol	riscv_elf_adjust_dynamic_symbol
+-#define elf_backend_size_dynamic_sections	riscv_elf_size_dynamic_sections
++#define elf_backend_late_size_sections		riscv_elf_late_size_sections
+ #define elf_backend_relocate_section		riscv_elf_relocate_section
+ #define elf_backend_finish_dynamic_symbol	riscv_elf_finish_dynamic_symbol
+ #define elf_backend_finish_dynamic_sections	riscv_elf_finish_dynamic_sections
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -9649,8 +9649,8 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
+    check for any mips16 stub sections that we can discard.  */
+ 
+ bool
+-_bfd_mips_elf_always_size_sections (bfd *output_bfd,
+-				    struct bfd_link_info *info)
++_bfd_mips_elf_early_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   asection *sect;
+   struct mips_elf_link_hash_table *htab;
+@@ -9993,8 +9993,8 @@ mips_elf_set_plt_sym_value (struct mips_
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_mips_elf_size_dynamic_sections (bfd *output_bfd,
+-				     struct bfd_link_info *info)
++_bfd_mips_elf_late_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   bfd *dynobj;
+   asection *s, *sreldyn;
+@@ -10004,7 +10004,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd
+   htab = mips_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = elf_hash_table (info)->dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+@@ -14938,7 +14939,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_always_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+@@ -14997,7 +14998,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_always_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+--- a/bfd/elfxx-mips.h
++++ b/bfd/elfxx-mips.h
+@@ -67,9 +67,9 @@ extern bool _bfd_mips_elf_check_relocs
+   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+ extern bool _bfd_mips_elf_adjust_dynamic_symbol
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+-extern bool _bfd_mips_elf_always_size_sections
++extern bool _bfd_mips_elf_early_size_sections
+   (bfd *, struct bfd_link_info *);
+-extern bool _bfd_mips_elf_size_dynamic_sections
++extern bool _bfd_mips_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern int _bfd_mips_elf_relocate_section
+   (bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
+--- a/bfd/elfxx-sparc.c
++++ b/bfd/elfxx-sparc.c
+@@ -2381,8 +2381,8 @@ _bfd_sparc_elf_omit_section_dynsym (bfd
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_sparc_elf_size_dynamic_sections (bfd *output_bfd,
+-				      struct bfd_link_info *info)
++_bfd_sparc_elf_late_size_sections (bfd *output_bfd,
++				   struct bfd_link_info *info)
+ {
+   struct _bfd_sparc_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2392,7 +2392,8 @@ _bfd_sparc_elf_size_dynamic_sections (bf
+   htab = _bfd_sparc_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+--- a/bfd/elfxx-sparc.h
++++ b/bfd/elfxx-sparc.h
+@@ -117,7 +117,7 @@ extern bool _bfd_sparc_elf_adjust_dynami
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+ extern bool _bfd_sparc_elf_omit_section_dynsym
+   (bfd *, struct bfd_link_info *, asection *);
+-extern bool _bfd_sparc_elf_size_dynamic_sections
++extern bool _bfd_sparc_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern bool _bfd_sparc_elf_new_section_hook
+   (bfd *, asection *);
+--- a/bfd/elfxx-target.h
++++ b/bfd/elfxx-target.h
+@@ -487,11 +487,11 @@
+ #ifndef elf_backend_adjust_dynamic_symbol
+ #define elf_backend_adjust_dynamic_symbol 0
+ #endif
+-#ifndef elf_backend_always_size_sections
+-#define elf_backend_always_size_sections 0
++#ifndef elf_backend_early_size_sections
++#define elf_backend_early_size_sections 0
+ #endif
+-#ifndef elf_backend_size_dynamic_sections
+-#define elf_backend_size_dynamic_sections 0
++#ifndef elf_backend_late_size_sections
++#define elf_backend_late_size_sections 0
+ #endif
+ #ifndef elf_backend_strip_zero_sized_dynamic_sections
+ #define elf_backend_strip_zero_sized_dynamic_sections 0
+@@ -853,8 +853,8 @@ static const struct elf_backend_data elf
+   elf_backend_check_directives,
+   elf_backend_notice_as_needed,
+   elf_backend_adjust_dynamic_symbol,
+-  elf_backend_always_size_sections,
+-  elf_backend_size_dynamic_sections,
++  elf_backend_early_size_sections,
++  elf_backend_late_size_sections,
+   elf_backend_strip_zero_sized_dynamic_sections,
+   elf_backend_init_index_section,
+   elf_backend_relocate_section,
+--- a/bfd/elfxx-tilegx.c
++++ b/bfd/elfxx-tilegx.c
+@@ -2430,8 +2430,8 @@ tilegx_elf_omit_section_dynsym (bfd *out
+ }
+ 
+ bool
+-tilegx_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+-				  struct bfd_link_info *info)
++tilegx_elf_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
++			       struct bfd_link_info *info)
+ {
+   struct tilegx_elf_link_hash_table *htab;
+   bfd *dynobj;
+@@ -2441,7 +2441,8 @@ tilegx_elf_size_dynamic_sections (bfd *o
+   htab = tilegx_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+   dynobj = htab->elf.dynobj;
+-  BFD_ASSERT (dynobj != NULL);
++  if (dynobj == NULL)
++    return true;
+ 
+   if (elf_hash_table (info)->dynamic_sections_created)
+     {
+--- a/bfd/elfxx-tilegx.h
++++ b/bfd/elfxx-tilegx.h
+@@ -57,7 +57,7 @@ tilegx_elf_omit_section_dynsym (bfd *,
+ 				asection *);
+ 
+ extern bool
+-tilegx_elf_size_dynamic_sections (bfd *, struct bfd_link_info *);
++tilegx_elf_late_size_sections (bfd *, struct bfd_link_info *);
+ 
+ extern int
+ tilegx_elf_relocate_section (bfd *, struct bfd_link_info *,
+--- a/bfd/elfxx-x86.c
++++ b/bfd/elfxx-x86.c
+@@ -2241,7 +2241,7 @@ _bfd_elf_x86_valid_reloc_p (asection *in
+ /* Set the sizes of the dynamic sections.  */
+ 
+ bool
+-_bfd_x86_elf_size_dynamic_sections (bfd *output_bfd,
++_bfd_x86_elf_late_size_sections (bfd *output_bfd,
+ 				    struct bfd_link_info *info)
+ {
+   struct elf_x86_link_hash_table *htab;
+@@ -2257,7 +2257,7 @@ _bfd_x86_elf_size_dynamic_sections (bfd
+     return false;
+   dynobj = htab->elf.dynobj;
+   if (dynobj == NULL)
+-    abort ();
++    return true;
+ 
+   /* Set up .got offsets for local syms, and space for local dynamic
+      relocs.  */
+@@ -3003,8 +3003,8 @@ _bfd_x86_elf_finish_dynamic_sections (bf
+ 
+ 
+ bool
+-_bfd_x86_elf_always_size_sections (bfd *output_bfd,
+-				   struct bfd_link_info *info)
++_bfd_x86_elf_early_size_sections (bfd *output_bfd,
++				  struct bfd_link_info *info)
+ {
+   asection *tls_sec = elf_hash_table (info)->tls_sec;
+ 
+--- a/bfd/elfxx-x86.h
++++ b/bfd/elfxx-x86.h
+@@ -850,13 +850,13 @@ extern bool _bfd_elf_x86_valid_reloc_p
+    const Elf_Internal_Rela *, struct elf_link_hash_entry *,
+    Elf_Internal_Sym *, Elf_Internal_Shdr *, bool *);
+ 
+-extern bool _bfd_x86_elf_size_dynamic_sections
++extern bool _bfd_x86_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ 
+ extern struct elf_x86_link_hash_table *_bfd_x86_elf_finish_dynamic_sections
+   (bfd *, struct bfd_link_info *);
+ 
+-extern bool _bfd_x86_elf_always_size_sections
++extern bool _bfd_x86_elf_early_size_sections
+   (bfd *, struct bfd_link_info *);
+ 
+ extern void _bfd_x86_elf_merge_symbol_attribute
+@@ -928,8 +928,8 @@ extern void _bfd_x86_elf_link_report_rel
+ 
+ #define elf_backend_check_relocs \
+   _bfd_x86_elf_check_relocs
+-#define elf_backend_size_dynamic_sections \
+-  _bfd_x86_elf_size_dynamic_sections
++#define elf_backend_late_size_sections \
++  _bfd_x86_elf_late_size_sections
+ #define elf_backend_merge_symbol_attribute \
+   _bfd_x86_elf_merge_symbol_attribute
+ #define elf_backend_copy_indirect_symbol \
+--- a/ld/emultempl/vms.em
++++ b/ld/emultempl/vms.em
+@@ -197,10 +197,9 @@ gld${EMULATION_NAME}_before_allocation (
+ 
+   /* The backend must work out the sizes of all the other dynamic
+      sections.  */
+-  if (elf_hash_table (&link_info)->dynamic_sections_created
+-      && bed->elf_backend_size_dynamic_sections
+-      && ! (*bed->elf_backend_size_dynamic_sections) (link_info.output_bfd,
+-						      &link_info))
++  if (bed->elf_backend_late_size_sections
++      && !bed->elf_backend_late_size_sections (link_info.output_bfd,
++					       &link_info))
+     einfo (_("%F%P: failed to set dynamic section sizes: %E\n"));
+ 
+   before_allocation_default ();
diff --git a/toolchain/binutils/patches/2.42/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch b/toolchain/binutils/patches/2.42/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch
new file mode 100644
index 0000000..49381a4
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/002-PR-30569-delete-_bfd_mips_elf_early_size_sections.patch
@@ -0,0 +1,218 @@
+From 3c6c32951e292a51ede70b8087bb0308d7dbc4fc Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Thu, 28 Mar 2024 20:33:32 +1030
+Subject: [PATCH 2/2] PR 30569, delete _bfd_mips_elf_early_size_sections
+
+PR30569 was triggered by a patch of mine 6540edd52cc0 moving the call
+to always_size_sections in bfd_elf_size_dynamic_sections earlier, made
+to support the x86 DT_RELR implementation.  This broke mips16 code
+handling stubs when --export-dynamic is passed to the linker, because
+numerous symbols then became dynamic after always_size_sections.  The
+mips backend fiddles with symbols in its always_size_sections.  Maciej
+in 902e9fc76a0e had moved the call to always_size_sections to after
+the export-dynamic code.  Prior to that, Nathan in 04c3a75556c0 moved
+it before the exec stack code, back to the start of
+bfd_elf_size_dynamic_sections which was where Ian put it originally
+in ff12f303355b.  So the call has moved around a little.  I'm leaving
+it where it is, and instead calling mips_elf_check_symbols from
+late_size_sections (the old size_dynamic_sections) which is now always
+called.  In fact, the whole of _bfd_mips_elf_early_size_sections can
+be merged into _bfd_mips_elf_late_size_sections.
+---
+ bfd/elf32-mips.c  |  1 -
+ bfd/elf64-mips.c  |  2 --
+ bfd/elfn32-mips.c |  1 -
+ bfd/elfxx-mips.c  | 84 +++++++++++++++++++----------------------------
+ bfd/elfxx-mips.h  |  2 --
+ 5 files changed, 34 insertions(+), 56 deletions(-)
+
+--- a/bfd/elf32-mips.c
++++ b/bfd/elf32-mips.c
+@@ -2537,7 +2537,6 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+--- a/bfd/elf64-mips.c
++++ b/bfd/elf64-mips.c
+@@ -4748,8 +4748,6 @@ const struct elf_size_info mips_elf64_si
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 				_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections \
+-				_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections \
+ 				_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+--- a/bfd/elfn32-mips.c
++++ b/bfd/elfn32-mips.c
+@@ -4138,7 +4138,6 @@ static const struct ecoff_debug_swap mip
+ #define elf_backend_get_target_dtag	_bfd_mips_elf_get_target_dtag
+ #define elf_backend_adjust_dynamic_symbol \
+ 					_bfd_mips_elf_adjust_dynamic_symbol
+-#define elf_backend_early_size_sections	_bfd_mips_elf_early_size_sections
+ #define elf_backend_late_size_sections	_bfd_mips_elf_late_size_sections
+ #define elf_backend_init_index_section	_bfd_elf_init_1_index_section
+ #define elf_backend_relocate_section	_bfd_mips_elf_relocate_section
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -9644,48 +9644,6 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
+   return _bfd_elf_adjust_dynamic_copy (info, h, s);
+ }
+ 
+-/* This function is called after all the input files have been read,
+-   and the input sections have been assigned to output sections.  We
+-   check for any mips16 stub sections that we can discard.  */
+-
+-bool
+-_bfd_mips_elf_early_size_sections (bfd *output_bfd,
+-				   struct bfd_link_info *info)
+-{
+-  asection *sect;
+-  struct mips_elf_link_hash_table *htab;
+-  struct mips_htab_traverse_info hti;
+-
+-  htab = mips_elf_hash_table (info);
+-  BFD_ASSERT (htab != NULL);
+-
+-  /* The .reginfo section has a fixed size.  */
+-  sect = bfd_get_section_by_name (output_bfd, ".reginfo");
+-  if (sect != NULL)
+-    {
+-      bfd_set_section_size (sect, sizeof (Elf32_External_RegInfo));
+-      sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
+-    }
+-
+-  /* The .MIPS.abiflags section has a fixed size.  */
+-  sect = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
+-  if (sect != NULL)
+-    {
+-      bfd_set_section_size (sect, sizeof (Elf_External_ABIFlags_v0));
+-      sect->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
+-    }
+-
+-  hti.info = info;
+-  hti.output_bfd = output_bfd;
+-  hti.error = false;
+-  mips_elf_link_hash_traverse (mips_elf_hash_table (info),
+-			       mips_elf_check_symbols, &hti);
+-  if (hti.error)
+-    return false;
+-
+-  return true;
+-}
+-
+ /* If the link uses a GOT, lay it out and work out its size.  */
+ 
+ static bool
+@@ -9990,7 +9948,8 @@ mips_elf_set_plt_sym_value (struct mips_
+   return true;
+ }
+ 
+-/* Set the sizes of the dynamic sections.  */
++/* Set the sizes of the dynamic sections, some mips non-dynamic sections,
++   and check for any mips16 stub sections that we can discard.  */
+ 
+ bool
+ _bfd_mips_elf_late_size_sections (bfd *output_bfd,
+@@ -10000,14 +9959,39 @@ _bfd_mips_elf_late_size_sections (bfd *o
+   asection *s, *sreldyn;
+   bool reltext;
+   struct mips_elf_link_hash_table *htab;
++  struct mips_htab_traverse_info hti;
+ 
+   htab = mips_elf_hash_table (info);
+   BFD_ASSERT (htab != NULL);
+-  dynobj = elf_hash_table (info)->dynobj;
++
++  /* The .reginfo section has a fixed size.  */
++  s = bfd_get_section_by_name (output_bfd, ".reginfo");
++  if (s != NULL)
++    {
++      bfd_set_section_size (s, sizeof (Elf32_External_RegInfo));
++      s->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
++    }
++
++  /* The .MIPS.abiflags section has a fixed size.  */
++  s = bfd_get_section_by_name (output_bfd, ".MIPS.abiflags");
++  if (s != NULL)
++    {
++      bfd_set_section_size (s, sizeof (Elf_External_ABIFlags_v0));
++      s->flags |= SEC_FIXED_SIZE | SEC_HAS_CONTENTS;
++    }
++
++  hti.info = info;
++  hti.output_bfd = output_bfd;
++  hti.error = false;
++  mips_elf_link_hash_traverse (htab, mips_elf_check_symbols, &hti);
++  if (hti.error)
++    return false;
++
++  dynobj = htab->root.dynobj;
+   if (dynobj == NULL)
+     return true;
+ 
+-  if (elf_hash_table (info)->dynamic_sections_created)
++  if (htab->root.dynamic_sections_created)
+     {
+       /* Set the contents of the .interp section to the interpreter.  */
+       if (bfd_link_executable (info) && !info->nointerp)
+@@ -10147,7 +10131,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	    }
+ 	}
+       else if (bfd_link_executable (info)
+-	       && ! mips_elf_hash_table (info)->use_rld_obj_head
++	       && !htab->use_rld_obj_head
+ 	       && startswith (name, ".rld_map"))
+ 	{
+ 	  /* We add a room for __rld_map.  It will be filled in by the
+@@ -10156,7 +10140,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	}
+       else if (SGI_COMPAT (output_bfd)
+ 	       && startswith (name, ".compact_rel"))
+-	s->size += mips_elf_hash_table (info)->compact_rel_size;
++	s->size += htab->compact_rel_size;
+       else if (s == htab->root.splt)
+ 	{
+ 	  /* If the last PLT entry has a branch delay slot, allocate
+@@ -10196,7 +10180,7 @@ _bfd_mips_elf_late_size_sections (bfd *o
+ 	}
+     }
+ 
+-  if (elf_hash_table (info)->dynamic_sections_created)
++  if (htab->root.dynamic_sections_created)
+     {
+       /* Add some entries to the .dynamic section.  We fill in the
+ 	 values later, in _bfd_mips_elf_finish_dynamic_sections, but we
+@@ -14939,7 +14923,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_late_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf_External_ABIFlags_v0));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+@@ -14998,7 +14982,7 @@ _bfd_mips_elf_final_link (bfd *abfd, str
+ 	      input_section->flags &= ~SEC_HAS_CONTENTS;
+ 	    }
+ 
+-	  /* Size has been set in _bfd_mips_elf_early_size_sections.  */
++	  /* Size has been set in _bfd_mips_elf_late_size_sections.  */
+ 	  BFD_ASSERT(o->size == sizeof (Elf32_External_RegInfo));
+ 
+ 	  /* Skip this section later on (I don't think this currently
+--- a/bfd/elfxx-mips.h
++++ b/bfd/elfxx-mips.h
+@@ -67,8 +67,6 @@ extern bool _bfd_mips_elf_check_relocs
+   (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *);
+ extern bool _bfd_mips_elf_adjust_dynamic_symbol
+   (struct bfd_link_info *, struct elf_link_hash_entry *);
+-extern bool _bfd_mips_elf_early_size_sections
+-  (bfd *, struct bfd_link_info *);
+ extern bool _bfd_mips_elf_late_size_sections
+   (bfd *, struct bfd_link_info *);
+ extern int _bfd_mips_elf_relocate_section
diff --git a/toolchain/binutils/patches/2.42/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.42/300-001_ld_makefile_patch.patch
new file mode 100644
index 0000000..64dae55
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/300-001_ld_makefile_patch.patch
@@ -0,0 +1,22 @@
+--- a/ld/Makefile.am
++++ b/ld/Makefile.am
+@@ -50,7 +50,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ 
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
+--- a/ld/Makefile.in
++++ b/ld/Makefile.in
+@@ -583,7 +583,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ BASEDIR = $(srcdir)/..
+ BFDDIR = $(BASEDIR)/bfd
+ INCDIR = $(BASEDIR)/include
diff --git a/toolchain/binutils/patches/2.42/400-mips_no_dynamic_linking_sym.patch b/toolchain/binutils/patches/2.42/400-mips_no_dynamic_linking_sym.patch
new file mode 100644
index 0000000..30f70c2
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/400-mips_no_dynamic_linking_sym.patch
@@ -0,0 +1,18 @@
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -8149,6 +8149,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
+       bh = NULL;
++      if (0) {
+       if (!(_bfd_generic_link_add_one_symbol
+ 	    (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
+ 	     NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
+@@ -8161,6 +8162,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ 	return false;
++      }
+ 
+       if (! mips_elf_hash_table (info)->use_rld_obj_head)
+ 	{
diff --git a/toolchain/binutils/patches/2.42/500-Change-default-emulation-for-mips64-linux.patch b/toolchain/binutils/patches/2.42/500-Change-default-emulation-for-mips64-linux.patch
new file mode 100644
index 0000000..df38fca
--- /dev/null
+++ b/toolchain/binutils/patches/2.42/500-Change-default-emulation-for-mips64-linux.patch
@@ -0,0 +1,48 @@
+--- a/bfd/config.bfd
++++ b/bfd/config.bfd
+@@ -962,8 +962,8 @@ case "${targ}" in
+     want64=true
+     ;;
+   mips64*el-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_le_vec
+-    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_le_vec mips_elf64_trad_be_vec"
++    targ_defvec=mips_elf64_trad_le_vec
++    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_be_vec"
+     ;;
+   mips64*-*-linux*-gnuabi64)
+     targ_defvec=mips_elf64_trad_be_vec
+@@ -971,8 +971,8 @@ case "${targ}" in
+     want64=true
+     ;;
+   mips64*-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_be_vec
+-    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
++    targ_defvec=mips_elf64_trad_be_vec
++    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_le_vec"
+     ;;
+   mips*el-*-linux*)
+     targ_defvec=mips_elf32_trad_le_vec
+--- a/ld/configure.tgt
++++ b/ld/configure.tgt
+@@ -597,8 +597,8 @@ mips64*el-*-linux-gnuabi64)
+ 			targ_extra_emuls="elf64btsmip elf32ltsmipn32 elf32btsmipn32 elf32ltsmip elf32btsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+-mips64*el-*-linux-*)	targ_emul=elf32ltsmipn32
+-			targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
++mips64*el-*-linux-*)	targ_emul=elf64ltsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32ltsmip elf32btsmip elf64btsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+ mips64*-*-linux-gnuabi64)
+@@ -606,8 +606,8 @@ mips64*-*-linux-gnuabi64)
+ 			targ_extra_emuls="elf64ltsmip elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+-mips64*-*-linux-*)	targ_emul=elf32btsmipn32
+-			targ_extra_emuls="elf32ltsmipn32 elf32btsmip elf32ltsmip elf64btsmip elf64ltsmip"
++mips64*-*-linux-*)	targ_emul=elf64btsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip elf64ltsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+ mips*el-*-linux-*)	targ_emul=elf32ltsmip
diff --git a/toolchain/binutils/patches/2.43.1/300-001_ld_makefile_patch.patch b/toolchain/binutils/patches/2.43.1/300-001_ld_makefile_patch.patch
new file mode 100644
index 0000000..64dae55
--- /dev/null
+++ b/toolchain/binutils/patches/2.43.1/300-001_ld_makefile_patch.patch
@@ -0,0 +1,22 @@
+--- a/ld/Makefile.am
++++ b/ld/Makefile.am
+@@ -50,7 +50,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ 
+ EMUL = @EMUL@
+ EMULATION_OFILES = @EMULATION_OFILES@
+--- a/ld/Makefile.in
++++ b/ld/Makefile.in
+@@ -583,7 +583,7 @@ AM_CFLAGS = $(WARN_CFLAGS) $(ELF_CFLAGS)
+ # We put the scripts in the directory $(scriptdir)/ldscripts.
+ # We can't put the scripts in $(datadir) because the SEARCH_DIR
+ # directives need to be different for native and cross linkers.
+-scriptdir = $(tooldir)/lib
++scriptdir = $(libdir)
+ BASEDIR = $(srcdir)/..
+ BFDDIR = $(BASEDIR)/bfd
+ INCDIR = $(BASEDIR)/include
diff --git a/toolchain/binutils/patches/2.43.1/400-mips_no_dynamic_linking_sym.patch b/toolchain/binutils/patches/2.43.1/400-mips_no_dynamic_linking_sym.patch
new file mode 100644
index 0000000..d0cc7dd
--- /dev/null
+++ b/toolchain/binutils/patches/2.43.1/400-mips_no_dynamic_linking_sym.patch
@@ -0,0 +1,18 @@
+--- a/bfd/elfxx-mips.c
++++ b/bfd/elfxx-mips.c
+@@ -8161,6 +8161,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       name = SGI_COMPAT (abfd) ? "_DYNAMIC_LINK" : "_DYNAMIC_LINKING";
+       bh = NULL;
++      if (0) {
+       if (!(_bfd_generic_link_add_one_symbol
+ 	    (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, 0,
+ 	     NULL, false, get_elf_backend_data (abfd)->collect, &bh)))
+@@ -8173,6 +8174,7 @@ _bfd_mips_elf_create_dynamic_sections (b
+ 
+       if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ 	return false;
++      }
+ 
+       if (! mips_elf_hash_table (info)->use_rld_obj_head)
+ 	{
diff --git a/toolchain/binutils/patches/2.43.1/500-Change-default-emulation-for-mips64-linux.patch b/toolchain/binutils/patches/2.43.1/500-Change-default-emulation-for-mips64-linux.patch
new file mode 100644
index 0000000..df38fca
--- /dev/null
+++ b/toolchain/binutils/patches/2.43.1/500-Change-default-emulation-for-mips64-linux.patch
@@ -0,0 +1,48 @@
+--- a/bfd/config.bfd
++++ b/bfd/config.bfd
+@@ -962,8 +962,8 @@ case "${targ}" in
+     want64=true
+     ;;
+   mips64*el-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_le_vec
+-    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_le_vec mips_elf64_trad_be_vec"
++    targ_defvec=mips_elf64_trad_le_vec
++    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_ntrad_be_vec mips_elf32_trad_le_vec mips_elf32_trad_be_vec mips_elf64_trad_be_vec"
+     ;;
+   mips64*-*-linux*-gnuabi64)
+     targ_defvec=mips_elf64_trad_be_vec
+@@ -971,8 +971,8 @@ case "${targ}" in
+     want64=true
+     ;;
+   mips64*-*-linux*)
+-    targ_defvec=mips_elf32_ntrad_be_vec
+-    targ_selvecs="mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_be_vec mips_elf64_trad_le_vec"
++    targ_defvec=mips_elf64_trad_be_vec
++    targ_selvecs="mips_elf32_ntrad_be_vec mips_elf32_ntrad_le_vec mips_elf32_trad_be_vec mips_elf32_trad_le_vec mips_elf64_trad_le_vec"
+     ;;
+   mips*el-*-linux*)
+     targ_defvec=mips_elf32_trad_le_vec
+--- a/ld/configure.tgt
++++ b/ld/configure.tgt
+@@ -597,8 +597,8 @@ mips64*el-*-linux-gnuabi64)
+ 			targ_extra_emuls="elf64btsmip elf32ltsmipn32 elf32btsmipn32 elf32ltsmip elf32btsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+-mips64*el-*-linux-*)	targ_emul=elf32ltsmipn32
+-			targ_extra_emuls="elf32btsmipn32 elf32ltsmip elf32btsmip elf64ltsmip elf64btsmip"
++mips64*el-*-linux-*)	targ_emul=elf64ltsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32ltsmip elf32btsmip elf64btsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+ mips64*-*-linux-gnuabi64)
+@@ -606,8 +606,8 @@ mips64*-*-linux-gnuabi64)
+ 			targ_extra_emuls="elf64ltsmip elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+-mips64*-*-linux-*)	targ_emul=elf32btsmipn32
+-			targ_extra_emuls="elf32ltsmipn32 elf32btsmip elf32ltsmip elf64btsmip elf64ltsmip"
++mips64*-*-linux-*)	targ_emul=elf64btsmip
++			targ_extra_emuls="elf32btsmipn32 elf32ltsmipn32 elf32btsmip elf32ltsmip elf64ltsmip"
+ 			targ_extra_libpath=$targ_extra_emuls
+ 			;;
+ mips*el-*-linux-*)	targ_emul=elf32ltsmip
diff --git a/toolchain/build_version b/toolchain/build_version
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/toolchain/build_version
@@ -0,0 +1 @@
+1
diff --git a/toolchain/fortify-headers/Makefile b/toolchain/fortify-headers/Makefile
new file mode 100644
index 0000000..7e6bad5
--- /dev/null
+++ b/toolchain/fortify-headers/Makefile
@@ -0,0 +1,30 @@
+#
+# Copyright (C) 2015 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/target.mk
+
+PKG_NAME:=fortify-headers
+PKG_VERSION:=1.1
+PKG_RELEASE=3
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_URL:=https://github.com/jvoisin/$(PKG_NAME).git
+PKG_SOURCE_DATE:=2019-04-14
+PKG_SOURCE_VERSION:=e3fee64643279c144efd3d6856ed4e818c0d5ca2
+PKG_MIRROR_HASH:=f2ce18b031aecbf43d18142941ece7c90691a8b4e96fbb1d5af94f24e5572dad
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+define Host/Compile
+	true
+endef
+
+define Host/Install
+	$(MAKE) -C $(HOST_BUILD_DIR) PREFIX="" DESTDIR="$(TOOLCHAIN_DIR)" install
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/fortify-headers/patches/001-__ppoll_time64.patch b/toolchain/fortify-headers/patches/001-__ppoll_time64.patch
new file mode 100644
index 0000000..05f8c71
--- /dev/null
+++ b/toolchain/fortify-headers/patches/001-__ppoll_time64.patch
@@ -0,0 +1,11 @@
+--- a/include/poll.h
++++ b/include/poll.h
+@@ -39,7 +39,7 @@ _FORTIFY_FN(poll) int poll(struct pollfd
+ 	return __orig_poll(__f, __n, __s);
+ }
+ 
+-#ifdef _GNU_SOURCE
++#if defined(_GNU_SOURCE) && !(defined(_REDIR_TIME64) && _REDIR_TIME64)
+ #undef ppoll
+ _FORTIFY_FN(ppoll) int ppoll(struct pollfd *__f, nfds_t __n, const struct timespec *__s,
+                              const sigset_t *__m)
diff --git a/toolchain/fortify-headers/patches/002-strings.h-add-__extension__-mark.patch b/toolchain/fortify-headers/patches/002-strings.h-add-__extension__-mark.patch
new file mode 100644
index 0000000..a07bb15
--- /dev/null
+++ b/toolchain/fortify-headers/patches/002-strings.h-add-__extension__-mark.patch
@@ -0,0 +1,24 @@
+From 9ee4b9bd8df55ebbd5f6426fda4a36e1958b64c5 Mon Sep 17 00:00:00 2001
+From: Matthias Van Parys <matthias.vanparys@softathome.com>
+Date: Mon, 10 Jul 2023 14:31:05 +0200
+Subject: [PATCH] strings.h: Add __extension__ mark to include_next to silence
+ -pedantic
+
+Add __extension__ before #include-next in strings.h as was done for all other header files in commits
+7fd984fcb532be01f68cddc194c09a7ca10c1ea6 and a9ffac8596b094da8563aa5dd5d81c946670afe
+---
+ include/strings.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/include/strings.h
++++ b/include/strings.h
+@@ -16,6 +16,9 @@
+ #ifndef _FORTIFY_STRINGS_H
+ #define _FORTIFY_STRINGS_H
+ 
++#ifndef __cplusplus
++__extension__
++#endif
+ #include_next <strings.h>
+ 
+ #if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
diff --git a/toolchain/gcc/Config.in b/toolchain/gcc/Config.in
new file mode 100644
index 0000000..b306040
--- /dev/null
+++ b/toolchain/gcc/Config.in
@@ -0,0 +1,64 @@
+# Choose gcc version.
+
+choice
+	prompt "GCC compiler Version" if TOOLCHAINOPTS
+	default GCC_USE_VERSION_13
+	help
+	  Select the version of gcc you wish to use.
+
+	config GCC_USE_VERSION_11
+		bool "gcc 11.x"
+
+	config GCC_USE_VERSION_12
+		bool "gcc 12.x"
+
+	config GCC_USE_VERSION_13
+		bool "gcc 13.x"
+
+	config GCC_USE_VERSION_14
+		bool "gcc 14.x"
+endchoice
+
+config GCC_USE_GRAPHITE
+	bool
+	prompt "Compile in support for the new Graphite framework in GCC 4.4+" if TOOLCHAINOPTS
+
+config EXTRA_GCC_CONFIG_OPTIONS
+	string
+	prompt "Additional gcc configure options" if TOOLCHAINOPTS
+	default ""
+	help
+	    Any additional gcc options you may want to include....
+
+config GCC_DEFAULT_PIE
+	bool
+	prompt "Build executable with PIE enabled by default" if TOOLCHAINOPTS
+	help
+	    Use gcc configure option --enable-default-pie to turn on -fPIE and -pie by default.
+
+config GCC_DEFAULT_SSP
+	bool
+	prompt "Build executable with Stack-Smashing Protection enabled by default" if TOOLCHAINOPTS
+	help
+	    Use gcc configure option --enable-default-ssp to turn on -fstack-protector-strong by default.
+
+config SJLJ_EXCEPTIONS
+	bool
+	prompt "Use setjump()/longjump() exceptions" if TOOLCHAINOPTS
+	help
+	    Use old setjump()/longjump() exceptions instead of the newer
+	    frame unwinding exceptions handling routines.  Warning: increases
+	    code size and runtime memory usage.
+
+config INSTALL_GFORTRAN
+	bool
+	prompt "Build/install fortran compiler?" if TOOLCHAINOPTS
+	help
+	    Build/install GNU fortran compiler ?
+
+config INSTALL_GCCGO
+	bool
+	prompt "Build/install Go compiler?" if TOOLCHAINOPTS
+	depends on USE_GLIBC || BROKEN
+	help
+	    Build/install GNU gccgo compiler ?
diff --git a/toolchain/gcc/Config.version b/toolchain/gcc/Config.version
new file mode 100644
index 0000000..2abf6c1
--- /dev/null
+++ b/toolchain/gcc/Config.version
@@ -0,0 +1,19 @@
+config GCC_VERSION_12
+	default y if GCC_USE_VERSION_12
+	bool
+
+config GCC_VERSION_14
+	default y if GCC_USE_VERSION_14
+	bool
+
+config GCC_VERSION
+	string
+	default EXTERNAL_GCC_VERSION	if EXTERNAL_TOOLCHAIN && !NATIVE_TOOLCHAIN
+	default "12.3.0"	if GCC_VERSION_12
+	default "14.2.0"	if GCC_VERSION_14
+	default "13.3.0"
+
+config GCC_USE_DEFAULT_VERSION
+	bool
+	default y if !TOOLCHAINOPTS || GCC_USE_VERSION_13
+	imply KERNEL_WERROR
diff --git a/toolchain/gcc/common.mk b/toolchain/gcc/common.mk
new file mode 100644
index 0000000..d7dc55e
--- /dev/null
+++ b/toolchain/gcc/common.mk
@@ -0,0 +1,240 @@
+#
+# Copyright (C) 2002-2003 Erik Andersen <andersen@uclibc.org>
+# Copyright (C) 2004 Manuel Novoa III <mjn3@uclibc.org>
+# Copyright (C) 2005-2006 Felix Fietkau <nbd@nbd.name>
+# Copyright (C) 2006-2014 OpenWrt.org
+#
+# 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 will 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gcc
+GCC_VERSION:=$(call qstrip,$(CONFIG_GCC_VERSION))
+PKG_VERSION:=$(firstword $(subst +, ,$(GCC_VERSION)))
+GCC_MAJOR_VERSION:=$(word 1,$(subst ., ,$(PKG_VERSION)))
+GCC_DIR:=$(PKG_NAME)-$(PKG_VERSION)
+
+PKG_SOURCE_URL:=@GNU/gcc/gcc-$(PKG_VERSION)
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_CPE_ID:=cpe:/a:gnu:gcc
+
+ifeq ($(PKG_VERSION),11.3.0)
+  PKG_HASH:=b47cf2818691f5b1e21df2bb38c795fac2cfbd640ede2d0a5e1c89e338a3ac39
+endif
+
+ifeq ($(PKG_VERSION),12.3.0)
+  PKG_HASH:=949a5d4f99e786421a93b532b22ffab5578de7321369975b91aec97adfda8c3b
+endif
+
+ifeq ($(PKG_VERSION),13.3.0)
+  PKG_HASH:=0845e9621c9543a13f484e94584a49ffc0129970e9914624235fc1d061a0c083
+endif
+
+ifeq ($(PKG_VERSION),14.2.0)
+  PKG_HASH:=a7b39bc69cbf9e25826c5a60ab26477001f7c08d85cec04bc0e29cabed6f3cc9
+endif
+
+PATCH_DIR=../patches-$(GCC_MAJOR_VERSION).x
+
+BUGURL=http://bugs.openwrt.org/
+PKGVERSION=OpenWrt GCC $(PKG_VERSION) $(REVISION)
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+HOST_SOURCE_DIR:=$(HOST_BUILD_DIR)
+ifeq ($(GCC_VARIANT),minimal)
+  GCC_BUILD_DIR:=$(HOST_BUILD_DIR)-$(GCC_VARIANT)
+else
+  HOST_BUILD_DIR:=$(HOST_BUILD_DIR)-$(GCC_VARIANT)
+  GCC_BUILD_DIR:=$(HOST_BUILD_DIR)
+endif
+
+HOST_STAMP_PREPARED:=$(HOST_BUILD_DIR)/.prepared
+HOST_STAMP_BUILT:=$(GCC_BUILD_DIR)/.built
+HOST_STAMP_CONFIGURED:=$(GCC_BUILD_DIR)/.configured
+HOST_STAMP_INSTALLED:=$(HOST_BUILD_PREFIX)/stamp/.gcc_$(GCC_VARIANT)_installed
+
+SEP:=,
+TARGET_LANGUAGES:="c,c++$(if $(CONFIG_INSTALL_GFORTRAN),$(SEP)fortran)$(if $(CONFIG_INSTALL_GCCGO),$(SEP)go)"
+
+TAR_OPTIONS += \
+	--exclude-from='$(CURDIR)/../exclude-testsuite' --exclude=gcc/ada/*.ad* \
+	--exclude=libjava
+
+# this needs to be without -L/-lzstd flags or other parts fail to build
+# use an absolute path to ensure it really picks up our version
+export ac_cv_search_ZSTD_compress=$(STAGING_DIR_HOST)/lib/libzstd.a -pthread
+export libgcc_cv_fixed_point=no
+ifdef CONFIG_INSTALL_GCCGO
+  export libgo_cv_c_split_stack_supported=no
+endif
+
+ifdef CONFIG_GCC_USE_GRAPHITE
+  GRAPHITE_CONFIGURE:= --with-isl=$(STAGING_DIR_HOST)
+else
+  GRAPHITE_CONFIGURE:= --without-isl --without-cloog
+endif
+
+GCC_CONFIGURE:= \
+	SHELL="$(BASH)" \
+	$(HOST_SOURCE_DIR)/configure \
+		--with-bugurl=$(BUGURL) \
+		--with-pkgversion="$(PKGVERSION)" \
+		--prefix=$(TOOLCHAIN_DIR) \
+		--build=$(GNU_HOST_NAME) \
+		--host=$(GNU_HOST_NAME) \
+		--target=$(REAL_GNU_TARGET_NAME) \
+		--with-gnu-ld \
+		--enable-target-optspace \
+		--disable-libgomp \
+		--disable-libmudflap \
+		--disable-multilib \
+		--disable-libmpx \
+		--disable-nls \
+		--disable-libssp \
+		$(GRAPHITE_CONFIGURE) \
+		--with-host-libstdcxx=-lstdc++ \
+		$(SOFT_FLOAT_CONFIG_OPTION) \
+		$(call qstrip,$(CONFIG_EXTRA_GCC_CONFIG_OPTIONS)) \
+		$(if $(CONFIG_mips64)$(CONFIG_mips64el),--with-arch=mips64 \
+			--with-abi=$(call qstrip,$(CONFIG_MIPS64_ABI))) \
+		$(if $(CONFIG_arc),--with-cpu=$(CONFIG_CPU_TYPE)) \
+		$(if $(CONFIG_powerpc64), $(if $(CONFIG_USE_MUSL),--with-abi=elfv2)) \
+		--with-system-zlib=$(STAGING_DIR_HOST) \
+		--with-zstd=$(STAGING_DIR_HOST) \
+		--with-gmp=$(STAGING_DIR_HOST) \
+		--with-mpfr=$(STAGING_DIR_HOST) \
+		--with-mpc=$(STAGING_DIR_HOST) \
+		--disable-decimal-float \
+		--with-diagnostics-color=auto-if-env \
+		--enable-__cxa_atexit \
+		--enable-libstdcxx-dual-abi \
+		--with-default-libstdcxx-abi=new
+ifneq ($(CONFIG_mips)$(CONFIG_mipsel),)
+  GCC_CONFIGURE += --with-mips-plt
+endif
+
+ifneq ($(CONFIG_GCC_DEFAULT_PIE),)
+  GCC_CONFIGURE+= \
+		--enable-default-pie
+endif
+
+ifneq ($(CONFIG_GCC_DEFAULT_SSP),)
+  GCC_CONFIGURE+= \
+		--enable-default-ssp
+endif
+
+ifneq ($(CONFIG_EXTRA_TARGET_ARCH),)
+  GCC_CONFIGURE+= \
+		--enable-biarch \
+		--enable-targets=$(call qstrip,$(CONFIG_EXTRA_TARGET_ARCH_NAME))-linux-$(TARGET_SUFFIX)
+endif
+
+ifdef CONFIG_sparc
+  GCC_CONFIGURE+= \
+		--enable-targets=all \
+		--with-long-double-128
+endif
+
+ifneq ($(GCC_ARCH),)
+  GCC_CONFIGURE+= --with-arch=$(GCC_ARCH)
+endif
+
+ifeq ($(CONFIG_arm),y)
+  GCC_CONFIGURE+= \
+	--with-cpu=$(word 1, $(subst +," ,$(CONFIG_CPU_TYPE)))
+
+  ifneq ($(CONFIG_SOFT_FLOAT),y)
+    GCC_CONFIGURE+= \
+		--with-fpu=$(word 2, $(subst +, ",$(CONFIG_CPU_TYPE))) \
+		--with-float=hard
+  endif
+
+  # Do not let TARGET_CFLAGS get poisoned by extra CPU optimization flags
+  # that do not belong here. The cpu,fpu type should be specified via
+  # --with-cpu and --with-fpu for ARM and not CFLAGS.
+  TARGET_CFLAGS:=$(filter-out -m%,$(call qstrip,$(TARGET_CFLAGS)))
+endif
+
+ifeq ($(CONFIG_TARGET_x86)$(CONFIG_USE_GLIBC)$(CONFIG_INSTALL_GCCGO),yyy)
+  TARGET_CFLAGS+=-fno-split-stack
+endif
+
+TARGET_CFLAGS := $(filter-out -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64,$(TARGET_CFLAGS))
+
+CFLAGS:=$(HOST_CFLAGS) -pipe
+ifneq ($(shell gcc --version 2>&1 | grep -E "Apple.(LLVM|clang)"),)
+  CFLAGS+= -fbracket-depth=512
+endif
+
+GCC_CONFIGURE+= \
+	CFLAGS="$(CFLAGS)" \
+	CXXFLAGS="$(CFLAGS)" \
+	CFLAGS_FOR_TARGET="$(TARGET_CFLAGS)" \
+	CXXFLAGS_FOR_TARGET="$(TARGET_CFLAGS)" \
+	GOCFLAGS_FOR_TARGET="$(TARGET_CFLAGS)"
+
+GCC_MAKE:= \
+	export SHELL="$(BASH)"; \
+	$(MAKE)
+
+define Host/SetToolchainInfo
+	$(SED) 's,TARGET_CROSS=.*,TARGET_CROSS=$(REAL_GNU_TARGET_NAME)-,' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,GCC_VERSION=.*,GCC_VERSION=$(GCC_VERSION),' $(TOOLCHAIN_DIR)/info.mk
+endef
+
+
+ifeq ($(GCC_MAJOR_VERSION),11)
+	GCC_VERSION_FILE:=gcc/version.c
+else
+	GCC_VERSION_FILE:=gcc/genversion.cc
+endif
+
+ifneq ($(GCC_PREPARE),)
+  define Host/Prepare
+	$(call Host/SetToolchainInfo)
+	$(call Host/Prepare/Default)
+	ln -snf $(GCC_DIR) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+	$(CP) $(SCRIPT_DIR)/config.{guess,sub} $(HOST_SOURCE_DIR)/
+	$(SED) 's,^MULTILIB_OSDIRNAMES,# MULTILIB_OSDIRNAMES,' $(HOST_SOURCE_DIR)/gcc/config/*/t-*
+	$(SED) 'd' $(HOST_SOURCE_DIR)/gcc/DEV-PHASE
+	$(SED) 's, DATESTAMP,,' $(HOST_SOURCE_DIR)/$(GCC_VERSION_FILE)
+	$(SED) 's,gcc_no_link=yes,gcc_no_link=no,' $(HOST_SOURCE_DIR)/libstdc++-v3/configure
+	mkdir -p $(GCC_BUILD_DIR)
+  endef
+else
+  define Host/Prepare
+	mkdir -p $(GCC_BUILD_DIR)
+  endef
+endif
+
+define Host/Configure
+	(cd $(GCC_BUILD_DIR) && rm -f config.cache; \
+		$(GCC_CONFIGURE) \
+	);
+endef
+
+define Host/Clean
+	rm -rf $(if $(GCC_PREPARE),$(HOST_SOURCE_DIR)) \
+		$(HOST_BUILD_PREFIX)/stamp/.gcc_* \
+		$(HOST_BUILD_PREFIX)/stamp/.binutils_* \
+		$(GCC_BUILD_DIR) \
+		$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME) \
+		$(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME) \
+		$(TOOLCHAIN_DIR)/bin/$(REAL_GNU_TARGET_NAME)-gc* \
+		$(TOOLCHAIN_DIR)/bin/$(REAL_GNU_TARGET_NAME)-c*
+endef
diff --git a/toolchain/gcc/exclude-testsuite b/toolchain/gcc/exclude-testsuite
new file mode 100644
index 0000000..37a8f24
--- /dev/null
+++ b/toolchain/gcc/exclude-testsuite
@@ -0,0 +1,9 @@
+gcc-*/gcc/testsuite/ada
+gcc-*/gcc/testsuite/brig.dg
+gcc-*/gcc/testsuite/c-c++-common
+gcc-*/gcc/testsuite/ChangeLog*
+gcc-*/gcc/testsuite/config
+gcc-*/gcc/testsuite/g*
+gcc-*/gcc/testsuite/jit.dg
+gcc-*/gcc/testsuite/lib
+gcc-*/gcc/testsuite/o*
diff --git a/toolchain/gcc/files/alternate-arch-cc.in b/toolchain/gcc/files/alternate-arch-cc.in
new file mode 100644
index 0000000..e169951
--- /dev/null
+++ b/toolchain/gcc/files/alternate-arch-cc.in
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+exec @CC_BASE@ @EXTRA_ARCH_OPTS@ "$@"
diff --git a/toolchain/gcc/final/Makefile b/toolchain/gcc/final/Makefile
new file mode 100644
index 0000000..78a5576
--- /dev/null
+++ b/toolchain/gcc/final/Makefile
@@ -0,0 +1,91 @@
+GCC_VARIANT:=final
+
+include ../common.mk
+
+GCC_CONFIGURE += \
+	--with-headers=$(TOOLCHAIN_DIR)/include \
+	--enable-languages=$(TARGET_LANGUAGES) \
+	--enable-shared \
+	--enable-threads \
+	--with-slibdir=$(TOOLCHAIN_DIR)/lib \
+	--enable-plugins \
+	--enable-lto \
+	--with-libelf=$(STAGING_DIR_HOST)
+
+ifndef CONFIG_USE_GLIBC
+  GCC_CONFIGURE += --disable-libsanitizer
+endif
+
+ifdef CONFIG_USE_MUSL
+  GCC_MAKE += gcc_cv_libc_provides_ssp=yes
+endif
+
+ifneq ($(CONFIG_SJLJ_EXCEPTIONS),)
+  GCC_CONFIGURE += \
+	--enable-sjlj-exceptions
+endif
+
+define CleanupToolchain
+	$(INSTALL_DIR) $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)
+	# Important!  Required for limits.h to be fixed.
+	rm -rf $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)/sys-include
+	ln -sf ../include $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)/sys-include
+	rm -rf $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)/lib
+	ln -sf ../lib $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)/lib
+	$(if $(CONFIG_ARCH_64BIT),ln -sf ../lib64 $(TOOLCHAIN_DIR)/$(REAL_GNU_TARGET_NAME)/lib64)
+endef
+
+define Host/Configure
+	$(CleanupToolchain)
+	mkdir -p $(GCC_BUILD_DIR)
+	(cd $(GCC_BUILD_DIR) && rm -f config.cache; \
+		$(GCC_CONFIGURE) \
+	);
+endef
+
+ifeq ($(CONFIG_USE_GLIBC)$(CONFIG_INSTALL_GCCGO),yy)
+define FixGogccCrt
+	# link crtX.o for gotools
+	mkdir -p $(GCC_BUILD_DIR)/gotools
+	$(foreach crt, i 1 n, ln -sf ../../glibc-dev/lib/crt$(crt).o $(GCC_BUILD_DIR)/gotools/ ; )
+endef
+endif
+
+define Host/Compile
+	$(FixGogccCrt)
+	+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) all
+endef
+
+define SetupExtraArch
+	for app in $(TOOLCHAIN_DIR)/bin/$(OPTIMIZE_FOR_CPU)*-{gcc,gcc-*,g++}; do \
+		[ -e $$$$app ] || continue; \
+		old_base=$$$$(basename $$$$app); \
+		new_base=$(call qstrip,$(CONFIG_EXTRA_TARGET_ARCH_NAME))-$$$${old_base##$(OPTIMIZE_FOR_CPU)-}; \
+		sed -e "s/@CC_BASE@/$$$$old_base/" \
+			-e 's/@EXTRA_ARCH_OPTS@/$(call qstrip,$(CONFIG_EXTRA_TARGET_ARCH_OPTS))/' \
+			 ../files/alternate-arch-cc.in > \
+			 $(TOOLCHAIN_DIR)/bin/$$$$new_base; \
+		chmod a+x $(TOOLCHAIN_DIR)/bin/$$$$new_base; \
+	done
+endef
+
+define Host/Install
+	$(CleanupToolchain)
+	+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) install
+	# Set up the symlinks to enable lying about target name.
+	set -e; \
+	(cd $(TOOLCHAIN_DIR); \
+		ln -sf $(REAL_GNU_TARGET_NAME) $(GNU_TARGET_NAME); \
+		cd bin; \
+		for app in $(REAL_GNU_TARGET_NAME)-* ; do \
+			ln -sf $$$${app} \
+		   	$(GNU_TARGET_NAME)$$$${app##$(REAL_GNU_TARGET_NAME)}; \
+		done; \
+	);
+	$(if $(CONFIG_EXTRA_TARGET_ARCH),$(call SetupExtraArch))
+	$(RM) $(TOOLCHAIN_DIR)/lib/libiberty.a
+	$(SCRIPT_DIR)/patch-specs.sh "$(TOOLCHAIN_DIR)"
+endef
+
+$(eval $(call HostBuild))
+
diff --git a/toolchain/gcc/initial/Makefile b/toolchain/gcc/initial/Makefile
new file mode 100644
index 0000000..7cb4a73
--- /dev/null
+++ b/toolchain/gcc/initial/Makefile
@@ -0,0 +1,28 @@
+GCC_VARIANT:=initial
+GCC_PREPARE=$(CONFIG_USE_MUSL)
+
+include ../common.mk
+
+GCC_CONFIGURE += \
+	--with-newlib \
+	--with-sysroot=$(TOOLCHAIN_DIR) \
+	--enable-languages=c \
+	--disable-shared \
+	--disable-threads \
+
+define Host/Compile
+	+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) \
+		all-build-libiberty \
+		all-gcc \
+		all-target-libgcc
+endef
+
+define Host/Install
+	+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) \
+		install-gcc \
+		install-target-libgcc
+
+	$(call FixupLibdir,$(TOOLCHAIN_DIR))
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/gcc/minimal/Makefile b/toolchain/gcc/minimal/Makefile
new file mode 100644
index 0000000..31d6f67
--- /dev/null
+++ b/toolchain/gcc/minimal/Makefile
@@ -0,0 +1,29 @@
+GCC_VARIANT:=minimal
+GCC_PREPARE=$(if $(CONFIG_USE_MUSL),,1)
+
+include ../common.mk
+
+GCC_CONFIGURE += \
+	--with-newlib \
+	--without-headers \
+	--enable-languages=c \
+	--disable-libsanitizer \
+	--disable-libssp \
+	--disable-shared \
+	--disable-threads
+
+define Host/Compile
+	+$(GCC_MAKE) $(HOST_JOBS) -C $(GCC_BUILD_DIR) all-gcc all-target-libgcc
+endef
+
+define Host/Install
+	$(GCC_MAKE) -C $(GCC_BUILD_DIR) install-gcc install-target-libgcc
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(GCC_BUILD_DIR)
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/gcc/patches-12.x/002-case_insensitive.patch b/toolchain/gcc/patches-12.x/002-case_insensitive.patch
new file mode 100644
index 0000000..409497e
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/002-case_insensitive.patch
@@ -0,0 +1,24 @@
+commit 81cc26c706b2bc8c8c1eb1a322e5c5157900836e
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Oct 19 21:45:51 2014 +0000
+
+    gcc: do not assume that the Mac OS X filesystem is case insensitive
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 42973
+
+--- a/include/filenames.h
++++ b/include/filenames.h
+@@ -44,11 +44,6 @@ extern "C" {
+ #  define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f)
+ #else /* not DOSish */
+-#  if defined(__APPLE__)
+-#    ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+-#      define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
+-#    endif
+-#  endif /* __APPLE__ */
+ #  define HAS_DRIVE_SPEC(f) (0)
+ #  define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f)
diff --git a/toolchain/gcc/patches-12.x/010-documentation.patch b/toolchain/gcc/patches-12.x/010-documentation.patch
new file mode 100644
index 0000000..39ee48e
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/010-documentation.patch
@@ -0,0 +1,35 @@
+commit 098bd91f5eae625c7d2ee621e10930fc4434e5e2
+Author: Luka Perkov <luka@openwrt.org>
+Date:   Tue Feb 26 16:16:33 2013 +0000
+
+    gcc: don't build documentation
+    
+    This closes #13039.
+    
+    Signed-off-by: Luka Perkov <luka@openwrt.org>
+    
+    SVN-Revision: 35807
+
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -3366,18 +3366,10 @@ doc/gcc.info: $(TEXI_GCC_FILES)
+ doc/gccint.info: $(TEXI_GCCINT_FILES)
+ doc/cppinternals.info: $(TEXI_CPPINT_FILES)
+ 
+-doc/%.info: %.texi
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I . -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/%.info:
+ 
+ # Duplicate entry to handle renaming of gccinstall.info
+-doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/gccinstall.info:
+ 
+ doc/cpp.dvi: $(TEXI_CPP_FILES)
+ doc/gcc.dvi: $(TEXI_GCC_FILES)
diff --git a/toolchain/gcc/patches-12.x/020-Include-safe-ctype.h-after-C-standard-headers-to-avo.patch b/toolchain/gcc/patches-12.x/020-Include-safe-ctype.h-after-C-standard-headers-to-avo.patch
new file mode 100644
index 0000000..986d190
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/020-Include-safe-ctype.h-after-C-standard-headers-to-avo.patch
@@ -0,0 +1,139 @@
+From 9970b576b7e4ae337af1268395ff221348c4b34a Mon Sep 17 00:00:00 2001
+From: Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+Date: Thu, 7 Mar 2024 14:36:03 +0100
+Subject: [PATCH] Include safe-ctype.h after C++ standard headers, to avoid
+ over-poisoning
+
+When building gcc's C++ sources against recent libc++, the poisoning of
+the ctype macros due to including safe-ctype.h before including C++
+standard headers such as <list>, <map>, etc, causes many compilation
+errors, similar to:
+
+  In file included from /home/dim/src/gcc/master/gcc/gensupport.cc:23:
+  In file included from /home/dim/src/gcc/master/gcc/system.h:233:
+  In file included from /usr/include/c++/v1/vector:321:
+  In file included from
+  /usr/include/c++/v1/__format/formatter_bool.h:20:
+  In file included from
+  /usr/include/c++/v1/__format/formatter_integral.h:32:
+  In file included from /usr/include/c++/v1/locale:202:
+  /usr/include/c++/v1/__locale:546:5: error: '__abi_tag__' attribute
+  only applies to structs, variables, functions, and namespaces
+    546 |     _LIBCPP_INLINE_VISIBILITY
+        |     ^
+  /usr/include/c++/v1/__config:813:37: note: expanded from macro
+  '_LIBCPP_INLINE_VISIBILITY'
+    813 | #  define _LIBCPP_INLINE_VISIBILITY _LIBCPP_HIDE_FROM_ABI
+        |                                     ^
+  /usr/include/c++/v1/__config:792:26: note: expanded from macro
+  '_LIBCPP_HIDE_FROM_ABI'
+    792 |
+    __attribute__((__abi_tag__(_LIBCPP_TOSTRING(
+  _LIBCPP_VERSIONED_IDENTIFIER))))
+        |                          ^
+  In file included from /home/dim/src/gcc/master/gcc/gensupport.cc:23:
+  In file included from /home/dim/src/gcc/master/gcc/system.h:233:
+  In file included from /usr/include/c++/v1/vector:321:
+  In file included from
+  /usr/include/c++/v1/__format/formatter_bool.h:20:
+  In file included from
+  /usr/include/c++/v1/__format/formatter_integral.h:32:
+  In file included from /usr/include/c++/v1/locale:202:
+  /usr/include/c++/v1/__locale:547:37: error: expected ';' at end of
+  declaration list
+    547 |     char_type toupper(char_type __c) const
+        |                                     ^
+  /usr/include/c++/v1/__locale:553:48: error: too many arguments
+  provided to function-like macro invocation
+    553 |     const char_type* toupper(char_type* __low, const
+    char_type* __high) const
+        |                                                ^
+  /home/dim/src/gcc/master/gcc/../include/safe-ctype.h:146:9: note:
+  macro 'toupper' defined here
+    146 | #define toupper(c) do_not_use_toupper_with_safe_ctype
+        |         ^
+
+This is because libc++ uses different transitive includes than
+libstdc++, and some of those transitive includes pull in various ctype
+declarations (typically via <locale>).
+
+There was already a special case for including <string> before
+safe-ctype.h, so move the rest of the C++ standard header includes to
+the same location, to fix the problem.
+
+gcc/ChangeLog:
+
+	* system.h: Include safe-ctype.h after C++ standard headers.
+
+Signed-off-by: Dimitry Andric <dimitry@andric.com>
+---
+ gcc/system.h | 39 ++++++++++++++++++---------------------
+ 1 file changed, 18 insertions(+), 21 deletions(-)
+
+diff --git a/gcc/system.h b/gcc/system.h
+index b0edab02885..ab29fc19776 100644
+--- a/gcc/system.h
++++ b/gcc/system.h
+@@ -194,27 +194,8 @@ extern int fprintf_unlocked (FILE *, const char *, ...);
+ #undef fread_unlocked
+ #undef fwrite_unlocked
+ 
+-/* Include <string> before "safe-ctype.h" to avoid GCC poisoning
+-   the ctype macros through safe-ctype.h */
+-
+-#ifdef __cplusplus
+-#ifdef INCLUDE_STRING
+-# include <string>
+-#endif
+-#endif
+-
+-/* There are an extraordinary number of issues with <ctype.h>.
+-   The last straw is that it varies with the locale.  Use libiberty's
+-   replacement instead.  */
+-#include "safe-ctype.h"
+-
+-#include <sys/types.h>
+-
+-#include <errno.h>
+-
+-#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
+-extern int errno;
+-#endif
++/* Include C++ standard headers before "safe-ctype.h" to avoid GCC
++   poisoning the ctype macros through safe-ctype.h */
+ 
+ #ifdef __cplusplus
+ #if defined (INCLUDE_ALGORITHM) || !defined (HAVE_SWAP_IN_UTILITY)
+@@ -229,6 +210,9 @@ extern int errno;
+ #ifdef INCLUDE_SET
+ # include <set>
+ #endif
++#ifdef INCLUDE_STRING
++# include <string>
++#endif
+ #ifdef INCLUDE_VECTOR
+ # include <vector>
+ #endif
+@@ -245,6 +229,19 @@ extern int errno;
+ # include <type_traits>
+ #endif
+ 
++/* There are an extraordinary number of issues with <ctype.h>.
++   The last straw is that it varies with the locale.  Use libiberty's
++   replacement instead.  */
++#include "safe-ctype.h"
++
++#include <sys/types.h>
++
++#include <errno.h>
++
++#if !defined (errno) && defined (HAVE_DECL_ERRNO) && !HAVE_DECL_ERRNO
++extern int errno;
++#endif
++
+ /* Some of glibc's string inlines cause warnings.  Plus we'd rather
+    rely on (and therefore test) GCC's string builtins.  */
+ #define __NO_STRING_INLINES
+-- 
+2.39.3
+
diff --git a/toolchain/gcc/patches-12.x/021-libcc1-fix-vector-include.patch b/toolchain/gcc/patches-12.x/021-libcc1-fix-vector-include.patch
new file mode 100644
index 0000000..b6b15cd
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/021-libcc1-fix-vector-include.patch
@@ -0,0 +1,65 @@
+From 5213047b1d50af63dfabb5e5649821a6cb157e33 Mon Sep 17 00:00:00 2001
+From: Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+Date: Sat, 16 Mar 2024 09:50:00 +0100
+Subject: [PATCH] libcc1: fix <vector> include
+
+Use INCLUDE_VECTOR before including system.h, instead of directly
+including <vector>, to avoid running into poisoned identifiers.
+
+Signed-off-by: Dimitry Andric <dimitry@andric.com>
+
+libcc1/ChangeLog:
+
+	PR middle-end/111632
+	* libcc1plugin.cc: Fix include.
+	* libcp1plugin.cc: Fix include.
+---
+ libcc1/libcc1plugin.cc | 3 +--
+ libcc1/libcp1plugin.cc | 3 +--
+ 2 files changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/libcc1/libcc1plugin.cc b/libcc1/libcc1plugin.cc
+index 72d17c3b81c..e64847466f4 100644
+--- a/libcc1/libcc1plugin.cc
++++ b/libcc1/libcc1plugin.cc
+@@ -32,6 +32,7 @@
+ #undef PACKAGE_VERSION
+ 
+ #define INCLUDE_MEMORY
++#define INCLUDE_VECTOR
+ #include "gcc-plugin.h"
+ #include "system.h"
+ #include "coretypes.h"
+@@ -69,8 +70,6 @@
+ #include "gcc-c-interface.h"
+ #include "context.hh"
+ 
+-#include <vector>
+-
+ using namespace cc1_plugin;
+ 
+ 
+diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
+index 0eff7c68d29..da68c5d0ac1 100644
+--- a/libcc1/libcp1plugin.cc
++++ b/libcc1/libcp1plugin.cc
+@@ -33,6 +33,7 @@
+ #undef PACKAGE_VERSION
+ 
+ #define INCLUDE_MEMORY
++#define INCLUDE_VECTOR
+ #include "gcc-plugin.h"
+ #include "system.h"
+ #include "coretypes.h"
+@@ -71,8 +72,6 @@
+ #include "rpc.hh"
+ #include "context.hh"
+ 
+-#include <vector>
+-
+ using namespace cc1_plugin;
+ 
+ 
+-- 
+2.39.3
+
diff --git a/toolchain/gcc/patches-12.x/110-Fix-MIPS-PR-84790.patch b/toolchain/gcc/patches-12.x/110-Fix-MIPS-PR-84790.patch
new file mode 100644
index 0000000..856fd6a
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/110-Fix-MIPS-PR-84790.patch
@@ -0,0 +1,20 @@
+Fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84790.
+MIPS16 functions have a static assembler prologue which clobbers
+registers v0 and v1. Add these register clobbers to function call
+instructions.
+
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -3134,6 +3134,12 @@ mips_emit_call_insn (rtx pattern, rtx or
+       emit_insn (gen_update_got_version ());
+     }
+ 
++  if (TARGET_MIPS16 && TARGET_USE_GOT)
++    {
++      clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), MIPS16_PIC_TEMP);
++      clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), MIPS_PROLOGUE_TEMP (word_mode));
++    }
++
+   if (TARGET_MIPS16
+       && TARGET_EXPLICIT_RELOCS
+       && TARGET_CALL_CLOBBERED_GP)
diff --git a/toolchain/gcc/patches-12.x/230-musl_libssp.patch b/toolchain/gcc/patches-12.x/230-musl_libssp.patch
new file mode 100644
index 0000000..a909d63
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/230-musl_libssp.patch
@@ -0,0 +1,13 @@
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -987,7 +987,9 @@ proper position among the other output f
+ #endif
+ 
+ #ifndef LINK_SSP_SPEC
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if DEFAULT_LIBC == LIBC_MUSL
++#define LINK_SSP_SPEC "-lssp_nonshared"
++#elif defined(TARGET_LIBC_PROVIDES_SSP)
+ #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ 		       "|fstack-protector-strong|fstack-protector-explicit:}"
+ #else
diff --git a/toolchain/gcc/patches-12.x/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches-12.x/300-mips_Os_cpu_rtx_cost_model.patch
new file mode 100644
index 0000000..1d223f2
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/300-mips_Os_cpu_rtx_cost_model.patch
@@ -0,0 +1,21 @@
+commit ecf7671b769fe96f7b5134be442089f8bdba55d2
+Author: Felix Fietkau <nbd@nbd.name>
+Date:   Thu Aug 4 20:29:45 2016 +0200
+
+gcc: add a patch to generate better code with Os on mips
+
+Also happens to reduce compressed code size a bit
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -20216,7 +20216,7 @@ mips_option_override (void)
+     flag_pcc_struct_return = 0;
+ 
+   /* Decide which rtx_costs structure to use.  */
+-  if (optimize_size)
++  if (0 && optimize_size)
+     mips_cost = &mips_rtx_cost_optimize_size;
+   else
+     mips_cost = &mips_rtx_cost_data[mips_tune];
diff --git a/toolchain/gcc/patches-12.x/700-RISCV-Inline-subword-atomic-ops.patch b/toolchain/gcc/patches-12.x/700-RISCV-Inline-subword-atomic-ops.patch
new file mode 100644
index 0000000..b164c76
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/700-RISCV-Inline-subword-atomic-ops.patch
@@ -0,0 +1,2021 @@
+From f797260adaf52bee0ec0e16190bbefbe1bfc3692 Mon Sep 17 00:00:00 2001
+From: Patrick O'Neill <patrick@rivosinc.com>
+Date: Tue, 18 Apr 2023 14:33:13 -0700
+Subject: [PATCH] RISCV: Inline subword atomic ops
+
+RISC-V has no support for subword atomic operations; code currently
+generates libatomic library calls.
+
+This patch changes the default behavior to inline subword atomic calls
+(using the same logic as the existing library call).
+Behavior can be specified using the -minline-atomics and
+-mno-inline-atomics command line flags.
+
+gcc/libgcc/config/riscv/atomic.c has the same logic implemented in asm.
+This will need to stay for backwards compatibility and the
+-mno-inline-atomics flag.
+
+2023-04-18 Patrick O'Neill <patrick@rivosinc.com>
+
+gcc/ChangeLog:
+	PR target/104338
+	* config/riscv/riscv-protos.h: Add helper function stubs.
+	* config/riscv/riscv.cc: Add helper functions for subword masking.
+	* config/riscv/riscv.opt: Add command-line flag.
+	* config/riscv/sync.md: Add masking logic and inline asm for fetch_and_op,
+	fetch_and_nand, CAS, and exchange ops.
+	* doc/invoke.texi: Add blurb regarding command-line flag.
+
+libgcc/ChangeLog:
+	PR target/104338
+	* config/riscv/atomic.c: Add reference to duplicate logic.
+
+gcc/testsuite/ChangeLog:
+	PR target/104338
+	* gcc.target/riscv/inline-atomics-1.c: New test.
+	* gcc.target/riscv/inline-atomics-2.c: New test.
+	* gcc.target/riscv/inline-atomics-3.c: New test.
+	* gcc.target/riscv/inline-atomics-4.c: New test.
+	* gcc.target/riscv/inline-atomics-5.c: New test.
+	* gcc.target/riscv/inline-atomics-6.c: New test.
+	* gcc.target/riscv/inline-atomics-7.c: New test.
+	* gcc.target/riscv/inline-atomics-8.c: New test.
+
+Signed-off-by: Patrick O'Neill <patrick@rivosinc.com>
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+---
+ gcc/config/riscv/riscv-protos.h               |   2 +
+ gcc/config/riscv/riscv.cc                     |  49 ++
+ gcc/config/riscv/riscv.opt                    |   4 +
+ gcc/config/riscv/sync.md                      | 301 +++++++++
+ gcc/doc/invoke.texi                           |  10 +-
+ .../gcc.target/riscv/inline-atomics-1.c       |  18 +
+ .../gcc.target/riscv/inline-atomics-2.c       |   9 +
+ .../gcc.target/riscv/inline-atomics-3.c       | 569 ++++++++++++++++++
+ .../gcc.target/riscv/inline-atomics-4.c       | 566 +++++++++++++++++
+ .../gcc.target/riscv/inline-atomics-5.c       |  87 +++
+ .../gcc.target/riscv/inline-atomics-6.c       |  87 +++
+ .../gcc.target/riscv/inline-atomics-7.c       |  69 +++
+ .../gcc.target/riscv/inline-atomics-8.c       |  69 +++
+ libgcc/config/riscv/atomic.c                  |   2 +
+ 14 files changed, 1841 insertions(+), 1 deletion(-)
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-1.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-2.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-3.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-4.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-5.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-6.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-7.c
+ create mode 100644 gcc/testsuite/gcc.target/riscv/inline-atomics-8.c
+
+--- a/gcc/config/riscv/riscv-protos.h
++++ b/gcc/config/riscv/riscv-protos.h
+@@ -74,6 +74,8 @@ extern bool riscv_expand_block_move (rtx
+ extern bool riscv_store_data_bypass_p (rtx_insn *, rtx_insn *);
+ extern rtx riscv_gen_gpr_save_insn (struct riscv_frame_info *);
+ extern bool riscv_gpr_save_operation_p (rtx);
++extern void riscv_subword_address (rtx, rtx *, rtx *, rtx *, rtx *);
++extern void riscv_lshift_subword (machine_mode, rtx, rtx, rtx *);
+ 
+ /* Routines implemented in riscv-c.cc.  */
+ void riscv_cpu_cpp_builtins (cpp_reader *);
+--- a/gcc/config/riscv/riscv.cc
++++ b/gcc/config/riscv/riscv.cc
+@@ -5605,6 +5605,55 @@ riscv_asan_shadow_offset (void)
+   return TARGET_64BIT ? (HOST_WIDE_INT_1 << 29) : 0;
+ }
+ 
++/* Given memory reference MEM, expand code to compute the aligned
++   memory address, shift and mask values and store them into
++   *ALIGNED_MEM, *SHIFT, *MASK and *NOT_MASK.  */
++
++void
++riscv_subword_address (rtx mem, rtx *aligned_mem, rtx *shift, rtx *mask,
++		       rtx *not_mask)
++{
++  /* Align the memory address to a word.  */
++  rtx addr = force_reg (Pmode, XEXP (mem, 0));
++
++  rtx addr_mask = gen_int_mode (-4, Pmode);
++
++  rtx aligned_addr = gen_reg_rtx (Pmode);
++  emit_move_insn (aligned_addr,  gen_rtx_AND (Pmode, addr, addr_mask));
++
++  *aligned_mem = change_address (mem, SImode, aligned_addr);
++
++  /* Calculate the shift amount.  */
++  emit_move_insn (*shift, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
++				       gen_int_mode (3, SImode)));
++  emit_move_insn (*shift, gen_rtx_ASHIFT (SImode, *shift,
++					  gen_int_mode (3, SImode)));
++
++  /* Calculate the mask.  */
++  int unshifted_mask = GET_MODE_MASK (GET_MODE (mem));
++
++  emit_move_insn (*mask, gen_int_mode (unshifted_mask, SImode));
++
++  emit_move_insn (*mask, gen_rtx_ASHIFT (SImode, *mask,
++					 gen_lowpart (QImode, *shift)));
++
++  emit_move_insn (*not_mask, gen_rtx_NOT(SImode, *mask));
++}
++
++/* Leftshift a subword within an SImode register.  */
++
++void
++riscv_lshift_subword (machine_mode mode, rtx value, rtx shift,
++		      rtx *shifted_value)
++{
++  rtx value_reg = gen_reg_rtx (SImode);
++  emit_move_insn (value_reg, simplify_gen_subreg (SImode, value,
++						  mode, 0));
++
++  emit_move_insn(*shifted_value, gen_rtx_ASHIFT (SImode, value_reg,
++						 gen_lowpart (QImode, shift)));
++}
++
+ /* Initialize the GCC target structure.  */
+ #undef TARGET_ASM_ALIGNED_HI_OP
+ #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
+--- a/gcc/config/riscv/riscv.opt
++++ b/gcc/config/riscv/riscv.opt
+@@ -209,6 +209,10 @@ int riscv_vector_elen_flags
+ TargetVariable
+ int riscv_zvl_flags
+ 
++minline-atomics
++Target Var(TARGET_INLINE_SUBWORD_ATOMIC) Init(1)
++Always inline subword atomic operations.
++
+ Enum
+ Name(isa_spec_class) Type(enum riscv_isa_spec_class)
+ Supported ISA specs (for use with the -misa-spec= option):
+--- a/gcc/config/riscv/sync.md
++++ b/gcc/config/riscv/sync.md
+@@ -21,8 +21,11 @@
+ 
+ (define_c_enum "unspec" [
+   UNSPEC_COMPARE_AND_SWAP
++  UNSPEC_COMPARE_AND_SWAP_SUBWORD
+   UNSPEC_SYNC_OLD_OP
++  UNSPEC_SYNC_OLD_OP_SUBWORD
+   UNSPEC_SYNC_EXCHANGE
++  UNSPEC_SYNC_EXCHANGE_SUBWORD
+   UNSPEC_ATOMIC_STORE
+   UNSPEC_MEMORY_BARRIER
+ ])
+@@ -92,6 +95,135 @@
+   "%F3amo<insn>.<amo>%A3 %0,%z2,%1"
+   [(set (attr "length") (const_int 8))])
+ 
++(define_insn "subword_atomic_fetch_strong_<atomic_optab>"
++  [(set (match_operand:SI 0 "register_operand" "=&r")		   ;; old value at mem
++	(match_operand:SI 1 "memory_operand" "+A"))		   ;; mem location
++   (set (match_dup 1)
++	(unspec_volatile:SI
++	  [(any_atomic:SI (match_dup 1)
++		     (match_operand:SI 2 "register_operand" "rI")) ;; value for op
++	   (match_operand:SI 3 "register_operand" "rI")]	   ;; mask
++	 UNSPEC_SYNC_OLD_OP_SUBWORD))
++    (match_operand:SI 4 "register_operand" "rI")		   ;; not_mask
++    (clobber (match_scratch:SI 5 "=&r"))			   ;; tmp_1
++    (clobber (match_scratch:SI 6 "=&r"))]			   ;; tmp_2
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++  {
++    return "1:\;"
++	   "lr.w.aq\t%0, %1\;"
++	   "<insn>\t%5, %0, %2\;"
++	   "and\t%5, %5, %3\;"
++	   "and\t%6, %0, %4\;"
++	   "or\t%6, %6, %5\;"
++	   "sc.w.rl\t%5, %6, %1\;"
++	   "bnez\t%5, 1b";
++  }
++  [(set (attr "length") (const_int 28))])
++
++(define_expand "atomic_fetch_nand<mode>"
++  [(match_operand:SHORT 0 "register_operand")			      ;; old value at mem
++   (not:SHORT (and:SHORT (match_operand:SHORT 1 "memory_operand")     ;; mem location
++			 (match_operand:SHORT 2 "reg_or_0_operand"))) ;; value for op
++   (match_operand:SI 3 "const_int_operand")]			      ;; model
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++{
++  /* We have no QImode/HImode atomics, so form a mask, then use
++     subword_atomic_fetch_strong_nand to implement a LR/SC version of the
++     operation. */
++
++  /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
++     is disabled */
++
++  rtx old = gen_reg_rtx (SImode);
++  rtx mem = operands[1];
++  rtx value = operands[2];
++  rtx aligned_mem = gen_reg_rtx (SImode);
++  rtx shift = gen_reg_rtx (SImode);
++  rtx mask = gen_reg_rtx (SImode);
++  rtx not_mask = gen_reg_rtx (SImode);
++
++  riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
++
++  rtx shifted_value = gen_reg_rtx (SImode);
++  riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
++
++  emit_insn (gen_subword_atomic_fetch_strong_nand (old, aligned_mem,
++						   shifted_value,
++						   mask, not_mask));
++
++  emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
++					 gen_lowpart (QImode, shift)));
++
++  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
++
++  DONE;
++})
++
++(define_insn "subword_atomic_fetch_strong_nand"
++  [(set (match_operand:SI 0 "register_operand" "=&r")			  ;; old value at mem
++	(match_operand:SI 1 "memory_operand" "+A"))			  ;; mem location
++   (set (match_dup 1)
++	(unspec_volatile:SI
++	  [(not:SI (and:SI (match_dup 1)
++			   (match_operand:SI 2 "register_operand" "rI"))) ;; value for op
++	   (match_operand:SI 3 "register_operand" "rI")]		  ;; mask
++	 UNSPEC_SYNC_OLD_OP_SUBWORD))
++    (match_operand:SI 4 "register_operand" "rI")			  ;; not_mask
++    (clobber (match_scratch:SI 5 "=&r"))				  ;; tmp_1
++    (clobber (match_scratch:SI 6 "=&r"))]				  ;; tmp_2
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++  {
++    return "1:\;"
++	   "lr.w.aq\t%0, %1\;"
++	   "and\t%5, %0, %2\;"
++	   "not\t%5, %5\;"
++	   "and\t%5, %5, %3\;"
++	   "and\t%6, %0, %4\;"
++	   "or\t%6, %6, %5\;"
++	   "sc.w.rl\t%5, %6, %1\;"
++	   "bnez\t%5, 1b";
++  }
++  [(set (attr "length") (const_int 32))])
++
++(define_expand "atomic_fetch_<atomic_optab><mode>"
++  [(match_operand:SHORT 0 "register_operand")			 ;; old value at mem
++   (any_atomic:SHORT (match_operand:SHORT 1 "memory_operand")	 ;; mem location
++		     (match_operand:SHORT 2 "reg_or_0_operand")) ;; value for op
++   (match_operand:SI 3 "const_int_operand")]			 ;; model
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++{
++  /* We have no QImode/HImode atomics, so form a mask, then use
++     subword_atomic_fetch_strong_<mode> to implement a LR/SC version of the
++     operation. */
++
++  /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
++     is disabled */
++
++  rtx old = gen_reg_rtx (SImode);
++  rtx mem = operands[1];
++  rtx value = operands[2];
++  rtx aligned_mem = gen_reg_rtx (SImode);
++  rtx shift = gen_reg_rtx (SImode);
++  rtx mask = gen_reg_rtx (SImode);
++  rtx not_mask = gen_reg_rtx (SImode);
++
++  riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
++
++  rtx shifted_value = gen_reg_rtx (SImode);
++  riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
++
++  emit_insn (gen_subword_atomic_fetch_strong_<atomic_optab> (old, aligned_mem,
++							     shifted_value,
++							     mask, not_mask));
++
++  emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
++					 gen_lowpart (QImode, shift)));
++
++  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
++
++  DONE;
++})
++
+ (define_insn "atomic_exchange<mode>"
+   [(set (match_operand:GPR 0 "register_operand" "=&r")
+ 	(unspec_volatile:GPR
+@@ -104,6 +236,56 @@
+   "%F3amoswap.<amo>%A3 %0,%z2,%1"
+   [(set (attr "length") (const_int 8))])
+ 
++(define_expand "atomic_exchange<mode>"
++  [(match_operand:SHORT 0 "register_operand") ;; old value at mem
++   (match_operand:SHORT 1 "memory_operand")   ;; mem location
++   (match_operand:SHORT 2 "register_operand") ;; value
++   (match_operand:SI 3 "const_int_operand")]  ;; model
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++{
++  rtx old = gen_reg_rtx (SImode);
++  rtx mem = operands[1];
++  rtx value = operands[2];
++  rtx aligned_mem = gen_reg_rtx (SImode);
++  rtx shift = gen_reg_rtx (SImode);
++  rtx mask = gen_reg_rtx (SImode);
++  rtx not_mask = gen_reg_rtx (SImode);
++
++  riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
++
++  rtx shifted_value = gen_reg_rtx (SImode);
++  riscv_lshift_subword (<MODE>mode, value, shift, &shifted_value);
++
++  emit_insn (gen_subword_atomic_exchange_strong (old, aligned_mem,
++						 shifted_value, not_mask));
++
++  emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
++					 gen_lowpart (QImode, shift)));
++
++  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
++  DONE;
++})
++
++(define_insn "subword_atomic_exchange_strong"
++  [(set (match_operand:SI 0 "register_operand" "=&r")	 ;; old value at mem
++	(match_operand:SI 1 "memory_operand" "+A"))	 ;; mem location
++   (set (match_dup 1)
++	(unspec_volatile:SI
++	  [(match_operand:SI 2 "reg_or_0_operand" "rI")  ;; value
++	   (match_operand:SI 3 "reg_or_0_operand" "rI")] ;; not_mask
++      UNSPEC_SYNC_EXCHANGE_SUBWORD))
++    (clobber (match_scratch:SI 4 "=&r"))]		 ;; tmp_1
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++  {
++    return "1:\;"
++	   "lr.w.aq\t%0, %1\;"
++	   "and\t%4, %0, %3\;"
++	   "or\t%4, %4, %2\;"
++	   "sc.w.rl\t%4, %4, %1\;"
++	   "bnez\t%4, 1b";
++  }
++  [(set (attr "length") (const_int 20))])
++
+ (define_insn "atomic_cas_value_strong<mode>"
+   [(set (match_operand:GPR 0 "register_operand" "=&r")
+ 	(match_operand:GPR 1 "memory_operand" "+A"))
+@@ -152,6 +334,125 @@
+   DONE;
+ })
+ 
++(define_expand "atomic_compare_and_swap<mode>"
++  [(match_operand:SI 0 "register_operand")    ;; bool output
++   (match_operand:SHORT 1 "register_operand") ;; val output
++   (match_operand:SHORT 2 "memory_operand")   ;; memory
++   (match_operand:SHORT 3 "reg_or_0_operand") ;; expected value
++   (match_operand:SHORT 4 "reg_or_0_operand") ;; desired value
++   (match_operand:SI 5 "const_int_operand")   ;; is_weak
++   (match_operand:SI 6 "const_int_operand")   ;; mod_s
++   (match_operand:SI 7 "const_int_operand")]  ;; mod_f
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++{
++  emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
++						operands[3], operands[4],
++						operands[6], operands[7]));
++
++  rtx val = gen_reg_rtx (SImode);
++  if (operands[1] != const0_rtx)
++    emit_move_insn (val, gen_rtx_SIGN_EXTEND (SImode, operands[1]));
++  else
++    emit_move_insn (val, const0_rtx);
++
++  rtx exp = gen_reg_rtx (SImode);
++  if (operands[3] != const0_rtx)
++    emit_move_insn (exp, gen_rtx_SIGN_EXTEND (SImode, operands[3]));
++  else
++    emit_move_insn (exp, const0_rtx);
++
++  rtx compare = val;
++  if (exp != const0_rtx)
++    {
++      rtx difference = gen_rtx_MINUS (SImode, val, exp);
++      compare = gen_reg_rtx (SImode);
++      emit_move_insn  (compare, difference);
++    }
++
++  if (word_mode != SImode)
++    {
++      rtx reg = gen_reg_rtx (word_mode);
++      emit_move_insn (reg, gen_rtx_SIGN_EXTEND (word_mode, compare));
++      compare = reg;
++    }
++
++  emit_move_insn (operands[0], gen_rtx_EQ (SImode, compare, const0_rtx));
++  DONE;
++})
++
++(define_expand "atomic_cas_value_strong<mode>"
++  [(match_operand:SHORT 0 "register_operand") ;; val output
++   (match_operand:SHORT 1 "memory_operand")   ;; memory
++   (match_operand:SHORT 2 "reg_or_0_operand") ;; expected value
++   (match_operand:SHORT 3 "reg_or_0_operand") ;; desired value
++   (match_operand:SI 4 "const_int_operand")   ;; mod_s
++   (match_operand:SI 5 "const_int_operand")   ;; mod_f
++   (match_scratch:SHORT 6)]
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++{
++  /* We have no QImode/HImode atomics, so form a mask, then use
++     subword_atomic_cas_strong<mode> to implement a LR/SC version of the
++     operation. */
++
++  /* Logic duplicated in gcc/libgcc/config/riscv/atomic.c for use when inlining
++     is disabled */
++
++  rtx old = gen_reg_rtx (SImode);
++  rtx mem = operands[1];
++  rtx aligned_mem = gen_reg_rtx (SImode);
++  rtx shift = gen_reg_rtx (SImode);
++  rtx mask = gen_reg_rtx (SImode);
++  rtx not_mask = gen_reg_rtx (SImode);
++
++  riscv_subword_address (mem, &aligned_mem, &shift, &mask, &not_mask);
++
++  rtx o = operands[2];
++  rtx n = operands[3];
++  rtx shifted_o = gen_reg_rtx (SImode);
++  rtx shifted_n = gen_reg_rtx (SImode);
++
++  riscv_lshift_subword (<MODE>mode, o, shift, &shifted_o);
++  riscv_lshift_subword (<MODE>mode, n, shift, &shifted_n);
++
++  emit_move_insn (shifted_o, gen_rtx_AND (SImode, shifted_o, mask));
++  emit_move_insn (shifted_n, gen_rtx_AND (SImode, shifted_n, mask));
++
++  emit_insn (gen_subword_atomic_cas_strong (old, aligned_mem,
++					    shifted_o, shifted_n,
++					    mask, not_mask));
++
++  emit_move_insn (old, gen_rtx_ASHIFTRT (SImode, old,
++					 gen_lowpart (QImode, shift)));
++
++  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, old));
++
++  DONE;
++})
++
++(define_insn "subword_atomic_cas_strong"
++  [(set (match_operand:SI 0 "register_operand" "=&r")			   ;; old value at mem
++	(match_operand:SI 1 "memory_operand" "+A"))			   ;; mem location
++   (set (match_dup 1)
++	(unspec_volatile:SI [(match_operand:SI 2 "reg_or_0_operand" "rJ")  ;; expected value
++			     (match_operand:SI 3 "reg_or_0_operand" "rJ")] ;; desired value
++	 UNSPEC_COMPARE_AND_SWAP_SUBWORD))
++	(match_operand:SI 4 "register_operand" "rI")			   ;; mask
++	(match_operand:SI 5 "register_operand" "rI")			   ;; not_mask
++	(clobber (match_scratch:SI 6 "=&r"))]				   ;; tmp_1
++  "TARGET_ATOMIC && TARGET_INLINE_SUBWORD_ATOMIC"
++  {
++    return "1:\;"
++	   "lr.w.aq\t%0, %1\;"
++	   "and\t%6, %0, %4\;"
++	   "bne\t%6, %z2, 1f\;"
++	   "and\t%6, %0, %5\;"
++	   "or\t%6, %6, %3\;"
++	   "sc.w.rl\t%6, %6, %1\;"
++	   "bnez\t%6, 1b\;"
++	   "1:";
++  }
++  [(set (attr "length") (const_int 28))])
++
+ (define_expand "atomic_test_and_set"
+   [(match_operand:QI 0 "register_operand" "")     ;; bool output
+    (match_operand:QI 1 "memory_operand" "+A")    ;; memory
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -753,7 +753,8 @@ Objective-C and Objective-C++ Dialects}.
+ -moverride=@var{string}  -mverbose-cost-dump @gol
+ -mstack-protector-guard=@var{guard} -mstack-protector-guard-reg=@var{sysreg} @gol
+ -mstack-protector-guard-offset=@var{offset} -mtrack-speculation @gol
+--moutline-atomics }
++-moutline-atomics
++-minline-atomics  -mno-inline-atomics}
+ 
+ @emph{Adapteva Epiphany Options}
+ @gccoptlist{-mhalf-reg-file  -mprefer-short-insn-regs @gol
+@@ -28035,6 +28036,13 @@ Do or don't use smaller but slower prolo
+ library function calls.  The default is to use fast inline prologues and
+ epilogues.
+ 
++@opindex minline-atomics
++@item -minline-atomics
++@itemx -mno-inline-atomics
++Do or don't use smaller but slower subword atomic emulation code that uses
++libatomic function calls.  The default is to use fast inline subword atomics
++that do not require libatomic.
++
+ @item -mshorten-memrefs
+ @itemx -mno-shorten-memrefs
+ @opindex mshorten-memrefs
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-1.c
+@@ -0,0 +1,18 @@
++/* { dg-do compile } */
++/* { dg-options "-mno-inline-atomics" } */
++/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
++/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_add_1" } } */
++/* { dg-final { scan-assembler "\tcall\t__sync_fetch_and_nand_1" } } */
++/* { dg-final { scan-assembler "\tcall\t__sync_bool_compare_and_swap_1" } } */
++
++char foo;
++char bar;
++char baz;
++
++int
++main ()
++{
++  __sync_fetch_and_add(&foo, 1);
++  __sync_fetch_and_nand(&bar, 1);
++  __sync_bool_compare_and_swap (&baz, 1, 2);
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-2.c
+@@ -0,0 +1,9 @@
++/* { dg-do compile } */
++/* Verify that subword atomics do not generate calls.  */
++/* { dg-options "-minline-atomics" } */
++/* { dg-message "note: '__sync_fetch_and_nand' changed semantics in GCC 4.4" "fetch_and_nand" { target *-*-* } 0 } */
++/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_add_1" } } */
++/* { dg-final { scan-assembler-not "\tcall\t__sync_fetch_and_nand_1" } } */
++/* { dg-final { scan-assembler-not "\tcall\t__sync_bool_compare_and_swap_1" } } */
++
++#include "inline-atomics-1.c"
+\ No newline at end of file
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-3.c
+@@ -0,0 +1,569 @@
++/* Check all char alignments.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-1.c */
++/* Test __atomic routines for existence and proper execution on 1 byte
++   values with each valid memory model.  */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */
++
++/* Test the execution of the __atomic_*OP builtin routines for a char.  */
++
++extern void abort(void);
++
++char count, res;
++const char init = ~0;
++
++struct A
++{
++   char a;
++   char b;
++   char c;
++   char d;
++} __attribute__ ((packed)) A;
++
++/* The fetch_op routines return the original value before the operation.  */
++
++void
++test_fetch_add (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
++    abort ();
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
++    abort ();
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
++    abort ();
++}
++
++
++void
++test_fetch_sub (char* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) !=  res--)
++    abort ();
++}
++
++void
++test_fetch_and (char* v)
++{
++  *v = init;
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_fetch_nand (char* v)
++{
++  *v = init;
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) !=  0 )
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) !=  0)
++    abort ();
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++void
++test_fetch_xor (char* v)
++{
++  *v = init;
++  count = 0;
++
++  if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) !=  0)
++    abort ();
++
++  if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++void
++test_fetch_or (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) !=  0)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) !=  1)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) !=  3)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) !=  7)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) !=  15)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) !=  31)
++    abort ();
++}
++
++/* The OP_fetch routines return the new value after the operation.  */
++
++void
++test_add_fetch (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
++    abort ();
++
++  if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
++    abort ();
++
++  if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
++    abort ();
++}
++
++
++void
++test_sub_fetch (char* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) !=  --res)
++    abort ();
++}
++
++void
++test_and_fetch (char* v)
++{
++  *v = init;
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) !=  0)
++    abort ();
++
++  *v = init;
++  if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_nand_fetch (char* v)
++{
++  *v = init;
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) !=  0)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++
++
++void
++test_xor_fetch (char* v)
++{
++  *v = init;
++  count = 0;
++
++  if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_or_fetch (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) !=  1)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) !=  3)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) !=  7)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) !=  15)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) !=  31)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) !=  63)
++    abort ();
++}
++
++
++/* Test the OP routines with a result which isn't used. Use both variations
++   within each function.  */
++
++void
++test_add (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != 1)
++    abort ();
++
++  __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
++  if (*v != 2)
++    abort ();
++
++  __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
++  if (*v != 3)
++    abort ();
++
++  __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
++  if (*v != 4)
++    abort ();
++
++  __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
++  if (*v != 5)
++    abort ();
++
++  __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
++  if (*v != 6)
++    abort ();
++}
++
++
++void
++test_sub (char* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
++  if (*v != --res)
++    abort ();
++
++  __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
++  if (*v != --res)
++    abort ();
++
++  __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
++  if (*v != --res)
++    abort ();
++}
++
++void
++test_and (char* v)
++{
++  *v = init;
++
++  __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
++  if (*v != 0)
++    abort ();
++
++  *v = init;
++  __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
++  if (*v != init)
++    abort ();
++
++  __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != 0)
++    abort ();
++
++  *v = ~*v;
++  __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
++  if (*v != init)
++    abort ();
++
++  __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
++  if (*v != 0)
++    abort ();
++
++  *v = ~*v;
++  __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
++  if (*v != 0)
++    abort ();
++}
++
++void
++test_nand (char* v)
++{
++  *v = init;
++
++  __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
++  if (*v != 0)
++    abort ();
++
++  __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != init)
++    abort ();
++
++  __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
++  if (*v != 0)
++    abort ();
++
++  __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
++  if (*v != init)
++    abort ();
++
++  __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
++  if (*v != init)
++    abort ();
++}
++
++
++
++void
++test_xor (char* v)
++{
++  *v = init;
++  count = 0;
++
++  __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
++  if (*v != 0)
++    abort ();
++
++  __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != 0)
++    abort ();
++
++  __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
++  if (*v != init)
++    abort ();
++
++  __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
++  if (*v != 0)
++    abort ();
++}
++
++void
++test_or (char* v)
++{
++  *v = 0;
++  count = 1;
++
++  __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != 1)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
++  if (*v != 3)
++    abort ();
++
++  count *= 2;
++  __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
++  if (*v != 7)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
++  if (*v != 15)
++    abort ();
++
++  count *= 2;
++  __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
++  if (*v != 31)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
++  if (*v != 63)
++    abort ();
++}
++
++int
++main ()
++{
++  char* V[] = {&A.a, &A.b, &A.c, &A.d};
++
++  for (int i = 0; i < 4; i++) {
++    test_fetch_add (V[i]);
++    test_fetch_sub (V[i]);
++    test_fetch_and (V[i]);
++    test_fetch_nand (V[i]);
++    test_fetch_xor (V[i]);
++    test_fetch_or (V[i]);
++
++    test_add_fetch (V[i]);
++    test_sub_fetch (V[i]);
++    test_and_fetch (V[i]);
++    test_nand_fetch (V[i]);
++    test_xor_fetch (V[i]);
++    test_or_fetch (V[i]);
++
++    test_add (V[i]);
++    test_sub (V[i]);
++    test_and (V[i]);
++    test_nand (V[i]);
++    test_xor (V[i]);
++    test_or (V[i]);
++  }
++
++  return 0;
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-4.c
+@@ -0,0 +1,566 @@
++/* Check all short alignments.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-op-2.c */
++/* Test __atomic routines for existence and proper execution on 2 byte
++   values with each valid memory model.  */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics -Wno-address-of-packed-member" } */
++
++/* Test the execution of the __atomic_*OP builtin routines for a short.  */
++
++extern void abort(void);
++
++short count, res;
++const short init = ~0;
++
++struct A
++{
++   short a;
++   short b;
++} __attribute__ ((packed)) A;
++
++/* The fetch_op routines return the original value before the operation.  */
++
++void
++test_fetch_add (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_RELAXED) != 0)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_CONSUME) != 1)
++    abort ();
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_ACQUIRE) != 2)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_RELEASE) != 3)
++    abort ();
++
++  if (__atomic_fetch_add (v, count, __ATOMIC_ACQ_REL) != 4)
++    abort ();
++
++  if (__atomic_fetch_add (v, 1, __ATOMIC_SEQ_CST) != 5)
++    abort ();
++}
++
++
++void
++test_fetch_sub (short* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_RELAXED) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_CONSUME) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQUIRE) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_RELEASE) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, count + 1, __ATOMIC_ACQ_REL) !=  res--)
++    abort ();
++
++  if (__atomic_fetch_sub (v, 1, __ATOMIC_SEQ_CST) !=  res--)
++    abort ();
++}
++
++void
++test_fetch_and (short* v)
++{
++  *v = init;
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, init, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_fetch_and (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_fetch_nand (short* v)
++{
++  *v = init;
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_ACQUIRE) !=  0 )
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL) !=  0)
++    abort ();
++
++  if (__atomic_fetch_nand (v, 0, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++void
++test_fetch_xor (short* v)
++{
++  *v = init;
++  count = 0;
++
++  if (__atomic_fetch_xor (v, count, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE) !=  0)
++    abort ();
++
++  if (__atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_fetch_xor (v, ~count, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++void
++test_fetch_or (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_fetch_or (v, count, __ATOMIC_RELAXED) !=  0)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, 2, __ATOMIC_CONSUME) !=  1)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_ACQUIRE) !=  3)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, 8, __ATOMIC_RELEASE) !=  7)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_ACQ_REL) !=  15)
++    abort ();
++
++  count *= 2;
++  if (__atomic_fetch_or (v, count, __ATOMIC_SEQ_CST) !=  31)
++    abort ();
++}
++
++/* The OP_fetch routines return the new value after the operation.  */
++
++void
++test_add_fetch (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_RELAXED) != 1)
++    abort ();
++
++  if (__atomic_add_fetch (v, 1, __ATOMIC_CONSUME) != 2)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_ACQUIRE) != 3)
++    abort ();
++
++  if (__atomic_add_fetch (v, 1, __ATOMIC_RELEASE) != 4)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_ACQ_REL) != 5)
++    abort ();
++
++  if (__atomic_add_fetch (v, count, __ATOMIC_SEQ_CST) != 6)
++    abort ();
++}
++
++
++void
++test_sub_fetch (short* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, 1, __ATOMIC_CONSUME) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQUIRE) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, 1, __ATOMIC_RELEASE) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL) !=  --res)
++    abort ();
++
++  if (__atomic_sub_fetch (v, count + 1, __ATOMIC_SEQ_CST) !=  --res)
++    abort ();
++}
++
++void
++test_and_fetch (short* v)
++{
++  *v = init;
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_RELAXED) !=  0)
++    abort ();
++
++  *v = init;
++  if (__atomic_and_fetch (v, init, __ATOMIC_CONSUME) !=  init)
++    abort ();
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_and_fetch (v, init, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL) !=  0)
++    abort ();
++
++  *v = ~*v;
++  if (__atomic_and_fetch (v, 0, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_nand_fetch (short* v)
++{
++  *v = init;
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_RELEASE) !=  0)
++    abort ();
++
++  if (__atomic_nand_fetch (v, init, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST) !=  init)
++    abort ();
++}
++
++
++
++void
++test_xor_fetch (short* v)
++{
++  *v = init;
++  count = 0;
++
++  if (__atomic_xor_fetch (v, count, __ATOMIC_RELAXED) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_CONSUME) !=  0)
++    abort ();
++
++  if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE) !=  0)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_RELEASE) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, 0, __ATOMIC_ACQ_REL) !=  init)
++    abort ();
++
++  if (__atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST) !=  0)
++    abort ();
++}
++
++void
++test_or_fetch (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  if (__atomic_or_fetch (v, count, __ATOMIC_RELAXED) !=  1)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, 2, __ATOMIC_CONSUME) !=  3)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_ACQUIRE) !=  7)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, 8, __ATOMIC_RELEASE) !=  15)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_ACQ_REL) !=  31)
++    abort ();
++
++  count *= 2;
++  if (__atomic_or_fetch (v, count, __ATOMIC_SEQ_CST) !=  63)
++    abort ();
++}
++
++
++/* Test the OP routines with a result which isn't used. Use both variations
++   within each function.  */
++
++void
++test_add (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  __atomic_add_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != 1)
++    abort ();
++
++  __atomic_fetch_add (v, count, __ATOMIC_CONSUME);
++  if (*v != 2)
++    abort ();
++
++  __atomic_add_fetch (v, 1 , __ATOMIC_ACQUIRE);
++  if (*v != 3)
++    abort ();
++
++  __atomic_fetch_add (v, 1, __ATOMIC_RELEASE);
++  if (*v != 4)
++    abort ();
++
++  __atomic_add_fetch (v, count, __ATOMIC_ACQ_REL);
++  if (*v != 5)
++    abort ();
++
++  __atomic_fetch_add (v, count, __ATOMIC_SEQ_CST);
++  if (*v != 6)
++    abort ();
++}
++
++
++void
++test_sub (short* v)
++{
++  *v = res = 20;
++  count = 0;
++
++  __atomic_sub_fetch (v, count + 1, __ATOMIC_RELAXED);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, count + 1, __ATOMIC_CONSUME);
++  if (*v != --res)
++    abort ();
++
++  __atomic_sub_fetch (v, 1, __ATOMIC_ACQUIRE);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, 1, __ATOMIC_RELEASE);
++  if (*v != --res)
++    abort ();
++
++  __atomic_sub_fetch (v, count + 1, __ATOMIC_ACQ_REL);
++  if (*v != --res)
++    abort ();
++
++  __atomic_fetch_sub (v, count + 1, __ATOMIC_SEQ_CST);
++  if (*v != --res)
++    abort ();
++}
++
++void
++test_and (short* v)
++{
++  *v = init;
++
++  __atomic_and_fetch (v, 0, __ATOMIC_RELAXED);
++  if (*v != 0)
++    abort ();
++
++  *v = init;
++  __atomic_fetch_and (v, init, __ATOMIC_CONSUME);
++  if (*v != init)
++    abort ();
++
++  __atomic_and_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != 0)
++    abort ();
++
++  *v = ~*v;
++  __atomic_fetch_and (v, init, __ATOMIC_RELEASE);
++  if (*v != init)
++    abort ();
++
++  __atomic_and_fetch (v, 0, __ATOMIC_ACQ_REL);
++  if (*v != 0)
++    abort ();
++
++  *v = ~*v;
++  __atomic_fetch_and (v, 0, __ATOMIC_SEQ_CST);
++  if (*v != 0)
++    abort ();
++}
++
++void
++test_nand (short* v)
++{
++  *v = init;
++
++  __atomic_fetch_nand (v, 0, __ATOMIC_RELAXED);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_nand (v, init, __ATOMIC_CONSUME);
++  if (*v != 0)
++    abort ();
++
++  __atomic_nand_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != init)
++    abort ();
++
++  __atomic_nand_fetch (v, init, __ATOMIC_RELEASE);
++  if (*v != 0)
++    abort ();
++
++  __atomic_fetch_nand (v, init, __ATOMIC_ACQ_REL);
++  if (*v != init)
++    abort ();
++
++  __atomic_nand_fetch (v, 0, __ATOMIC_SEQ_CST);
++  if (*v != init)
++    abort ();
++}
++
++
++
++void
++test_xor (short* v)
++{
++  *v = init;
++  count = 0;
++
++  __atomic_xor_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_xor (v, ~count, __ATOMIC_CONSUME);
++  if (*v != 0)
++    abort ();
++
++  __atomic_xor_fetch (v, 0, __ATOMIC_ACQUIRE);
++  if (*v != 0)
++    abort ();
++
++  __atomic_fetch_xor (v, ~count, __ATOMIC_RELEASE);
++  if (*v != init)
++    abort ();
++
++  __atomic_fetch_xor (v, 0, __ATOMIC_ACQ_REL);
++  if (*v != init)
++    abort ();
++
++  __atomic_xor_fetch (v, ~count, __ATOMIC_SEQ_CST);
++  if (*v != 0)
++    abort ();
++}
++
++void
++test_or (short* v)
++{
++  *v = 0;
++  count = 1;
++
++  __atomic_or_fetch (v, count, __ATOMIC_RELAXED);
++  if (*v != 1)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, count, __ATOMIC_CONSUME);
++  if (*v != 3)
++    abort ();
++
++  count *= 2;
++  __atomic_or_fetch (v, 4, __ATOMIC_ACQUIRE);
++  if (*v != 7)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, 8, __ATOMIC_RELEASE);
++  if (*v != 15)
++    abort ();
++
++  count *= 2;
++  __atomic_or_fetch (v, count, __ATOMIC_ACQ_REL);
++  if (*v != 31)
++    abort ();
++
++  count *= 2;
++  __atomic_fetch_or (v, count, __ATOMIC_SEQ_CST);
++  if (*v != 63)
++    abort ();
++}
++
++int
++main () {
++  short* V[] = {&A.a, &A.b};
++
++  for (int i = 0; i < 2; i++) {
++    test_fetch_add (V[i]);
++    test_fetch_sub (V[i]);
++    test_fetch_and (V[i]);
++    test_fetch_nand (V[i]);
++    test_fetch_xor (V[i]);
++    test_fetch_or (V[i]);
++
++    test_add_fetch (V[i]);
++    test_sub_fetch (V[i]);
++    test_and_fetch (V[i]);
++    test_nand_fetch (V[i]);
++    test_xor_fetch (V[i]);
++    test_or_fetch (V[i]);
++
++    test_add (V[i]);
++    test_sub (V[i]);
++    test_and (V[i]);
++    test_nand (V[i]);
++    test_xor (V[i]);
++    test_or (V[i]);
++  }
++
++  return 0;
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-5.c
+@@ -0,0 +1,87 @@
++/* Test __atomic routines for existence and proper execution on 1 byte
++   values with each valid memory model.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-1.c */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics" } */
++
++/* Test the execution of the __atomic_compare_exchange_n builtin for a char.  */
++
++extern void abort(void);
++
++char v = 0;
++char expected = 0;
++char max = ~0;
++char desired = ~0;
++char zero = 0;
++
++#define STRONG 0
++#define WEAK 1
++
++int
++main ()
++{
++
++  if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != max)
++    abort ();
++
++  if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != max)
++    abort ();
++  if (v != 0)
++    abort ();
++
++  if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
++    abort ();
++  if (expected != 0)
++    abort ();
++  if (v != max)
++    abort ();
++
++  /* Now test the generic version.  */
++
++  v = 0;
++
++  if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != max)
++    abort ();
++
++  if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != max)
++    abort ();
++  if (v != 0)
++    abort ();
++
++  if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
++    abort ();
++  if (expected != 0)
++    abort ();
++  if (v != max)
++    abort ();
++
++  return 0;
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-6.c
+@@ -0,0 +1,87 @@
++/* Test __atomic routines for existence and proper execution on 2 byte
++   values with each valid memory model.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-compare-exchange-2.c */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics" } */
++
++/* Test the execution of the __atomic_compare_exchange_n builtin for a short.  */
++
++extern void abort(void);
++
++short v = 0;
++short expected = 0;
++short max = ~0;
++short desired = ~0;
++short zero = 0;
++
++#define STRONG 0
++#define WEAK 1
++
++int
++main ()
++{
++
++  if (!__atomic_compare_exchange_n (&v, &expected, max, STRONG , __ATOMIC_RELAXED, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != max)
++    abort ();
++
++  if (!__atomic_compare_exchange_n (&v, &expected, 0, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != max)
++    abort ();
++  if (v != 0)
++    abort ();
++
++  if (__atomic_compare_exchange_n (&v, &expected, desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (!__atomic_compare_exchange_n (&v, &expected, desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
++    abort ();
++  if (expected != 0)
++    abort ();
++  if (v != max)
++    abort ();
++
++  /* Now test the generic version.  */
++
++  v = 0;
++
++  if (!__atomic_compare_exchange (&v, &expected, &max, STRONG, __ATOMIC_RELAXED, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_ACQUIRE, __ATOMIC_RELAXED))
++    abort ();
++  if (expected != max)
++    abort ();
++
++  if (!__atomic_compare_exchange (&v, &expected, &zero, STRONG , __ATOMIC_RELEASE, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != max)
++    abort ();
++  if (v != 0)
++    abort ();
++
++  if (__atomic_compare_exchange (&v, &expected, &desired, WEAK, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE))
++    abort ();
++  if (expected != 0)
++    abort ();
++
++  if (!__atomic_compare_exchange (&v, &expected, &desired, STRONG , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST))
++    abort ();
++  if (expected != 0)
++    abort ();
++  if (v != max)
++    abort ();
++
++  return 0;
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-7.c
+@@ -0,0 +1,69 @@
++/* Test __atomic routines for existence and proper execution on 1 byte
++   values with each valid memory model.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-1.c */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics" } */
++
++/* Test the execution of the __atomic_exchange_n builtin for a char.  */
++
++extern void abort(void);
++
++char v, count, ret;
++
++int
++main ()
++{
++  v = 0;
++  count = 0;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
++    abort ();
++  count++;
++
++  /* Now test the generic version.  */
++
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  return 0;
++}
+--- /dev/null
++++ b/gcc/testsuite/gcc.target/riscv/inline-atomics-8.c
+@@ -0,0 +1,69 @@
++/* Test __atomic routines for existence and proper execution on 2 byte
++   values with each valid memory model.  */
++/* Duplicate logic as libatomic/testsuite/libatomic.c/atomic-exchange-2.c */
++/* { dg-do run } */
++/* { dg-options "-minline-atomics" } */
++
++/* Test the execution of the __atomic_X builtin for a short.  */
++
++extern void abort(void);
++
++short v, count, ret;
++
++int
++main ()
++{
++  v = 0;
++  count = 0;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELAXED) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQUIRE) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_RELEASE) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_ACQ_REL) != count)
++    abort ();
++  count++;
++
++  if (__atomic_exchange_n (&v, count + 1, __ATOMIC_SEQ_CST) != count)
++    abort ();
++  count++;
++
++  /* Now test the generic version.  */
++
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_RELAXED);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQUIRE);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_RELEASE);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_ACQ_REL);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  __atomic_exchange (&v, &count, &ret, __ATOMIC_SEQ_CST);
++  if (ret != count - 1 || v != count)
++    abort ();
++  count++;
++
++  return 0;
++}
+--- a/libgcc/config/riscv/atomic.c
++++ b/libgcc/config/riscv/atomic.c
+@@ -30,6 +30,8 @@ see the files COPYING3 and COPYING.RUNTI
+ #define INVERT		"not %[tmp1], %[tmp1]\n\t"
+ #define DONT_INVERT	""
+ 
++/* Logic duplicated in gcc/gcc/config/riscv/sync.md for use when inlining is enabled */
++
+ #define GENERATE_FETCH_AND_OP(type, size, opname, insn, invert, cop)	\
+   type __sync_fetch_and_ ## opname ## _ ## size (type *p, type v)	\
+   {									\
diff --git a/toolchain/gcc/patches-12.x/701-riscv-linux-Don-t-add-latomic-with-pthread.patch b/toolchain/gcc/patches-12.x/701-riscv-linux-Don-t-add-latomic-with-pthread.patch
new file mode 100644
index 0000000..328c7be
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/701-riscv-linux-Don-t-add-latomic-with-pthread.patch
@@ -0,0 +1,36 @@
+From 203f3060dd363361b172f7295f42bb6bf5ac0b3b Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@suse.de>
+Date: Sat, 23 Apr 2022 15:48:42 +0200
+Subject: [PATCH] riscv/linux: Don't add -latomic with -pthread
+
+Now that we have support for inline subword atomic operations, it is no
+longer necessary to link against libatomic.  This also fixes testsuite
+failures because the framework does not properly set up the linker flags
+for finding libatomic.
+The use of atomic operations is also independent of the use of libpthread.
+
+gcc/
+	* config/riscv/linux.h (LIB_SPEC): Don't redefine.
+---
+ gcc/config/riscv/linux.h | 10 ----------
+ 1 file changed, 10 deletions(-)
+
+--- a/gcc/config/riscv/linux.h
++++ b/gcc/config/riscv/linux.h
+@@ -35,16 +35,6 @@ along with GCC; see the file COPYING3.
+ #undef MUSL_DYNAMIC_LINKER
+ #define MUSL_DYNAMIC_LINKER "/lib/ld-musl-riscv" XLEN_SPEC MUSL_ABI_SUFFIX ".so.1"
+ 
+-/* Because RISC-V only has word-sized atomics, it requries libatomic where
+-   others do not.  So link libatomic by default, as needed.  */
+-#undef LIB_SPEC
+-#ifdef LD_AS_NEEDED_OPTION
+-#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC \
+-  " %{pthread:" LD_AS_NEEDED_OPTION " -latomic " LD_NO_AS_NEEDED_OPTION "}"
+-#else
+-#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC " -latomic "
+-#endif
+-
+ #define ICACHE_FLUSH_FUNC "__riscv_flush_icache"
+ 
+ #define CPP_SPEC "%{pthread:-D_REENTRANT}"
diff --git a/toolchain/gcc/patches-12.x/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches-12.x/810-arm-softfloat-libgcc.patch
new file mode 100644
index 0000000..5c9d86a
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/810-arm-softfloat-libgcc.patch
@@ -0,0 +1,33 @@
+commit 8570c4be394cff7282f332f97da2ff569a927ddb
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 20:06:12 2011 +0000
+
+    fixup arm soft-float symbols
+    
+    SVN-Revision: 25325
+
+--- a/libgcc/config/arm/t-linux
++++ b/libgcc/config/arm/t-linux
+@@ -1,6 +1,10 @@
+ LIB1ASMSRC = arm/lib1funcs.S
+ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
+-	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3
++	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3 \
++	_arm_negdf2 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
++	_arm_fixdfsi _arm_fixunsdfsi _arm_truncdfsf2 \
++	_arm_negsf2 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
++	_arm_fixsfsi _arm_fixunssfsi
+ 
+ # Just for these, we omit the frame pointer since it makes such a big
+ # difference.
+--- a/gcc/config/arm/linux-elf.h
++++ b/gcc/config/arm/linux-elf.h
+@@ -58,8 +58,6 @@
+    %{shared:-lc} \
+    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+ 
+-#define LIBGCC_SPEC "%{mfloat-abi=soft*:-lfloat} -lgcc"
+-
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+ 
+ #define LINUX_TARGET_LINK_SPEC  "%{h*} \
diff --git a/toolchain/gcc/patches-12.x/820-libgcc_pic.patch b/toolchain/gcc/patches-12.x/820-libgcc_pic.patch
new file mode 100644
index 0000000..525a95b
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/820-libgcc_pic.patch
@@ -0,0 +1,44 @@
+commit c96312958c0621e72c9b32da5bc224ffe2161384
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Oct 19 23:26:09 2009 +0000
+
+    gcc: create a proper libgcc_pic.a static library for relinking (4.3.3+ for now, backport will follow)
+    
+    SVN-Revision: 18086
+
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -930,11 +930,12 @@ $(libgcov-driver-objects): %$(objext): $
+ 
+ # Static libraries.
+ libgcc.a: $(libgcc-objects)
++libgcc_pic.a: $(libgcc-s-objects)
+ libgcov.a: $(libgcov-objects)
+ libunwind.a: $(libunwind-objects)
+ libgcc_eh.a: $(libgcc-eh-objects)
+ 
+-libgcc.a libgcov.a libunwind.a libgcc_eh.a:
++libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a:
+ 	-rm -f $@
+ 
+ 	objects="$(objects)";					\
+@@ -958,7 +959,7 @@ all: libunwind.a
+ endif
+ 
+ ifeq ($(enable_shared),yes)
+-all: libgcc_eh.a libgcc_s$(SHLIB_EXT)
++all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT)
+ ifneq ($(LIBUNWIND),)
+ all: libunwind$(SHLIB_EXT)
+ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT)
+@@ -1164,6 +1165,10 @@ install-shared:
+ 	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 
++	$(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/
++	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++
+ 	$(subst @multilib_dir@,$(MULTIDIR),$(subst \
+ 		@shlib_base_name@,libgcc_s,$(subst \
+ 		@shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL))))
diff --git a/toolchain/gcc/patches-12.x/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches-12.x/840-armv4_pass_fix-v4bx_to_ld.patch
new file mode 100644
index 0000000..e3cb616
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/840-armv4_pass_fix-v4bx_to_ld.patch
@@ -0,0 +1,28 @@
+commit 7edc8ca5456d9743dd0075eb3cc5b04f4f24c8cc
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 19:34:36 2011 +0000
+
+    add armv4 fixup patches
+    
+    SVN-Revision: 25322
+
+
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -91,10 +91,15 @@
+ #define MUSL_DYNAMIC_LINKER \
+   "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}%{mfdpic:-fdpic}.so.1"
+ 
++/* For armv4 we pass --fix-v4bx to linker to support EABI */
++#undef TARGET_FIX_V4BX_SPEC
++#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*"\
++  "|march=armv4|mcpu=fa526|mcpu=fa626:--fix-v4bx}"
++
+ /* At this point, bpabi.h will have clobbered LINK_SPEC.  We want to
+    use the GNU/Linux version, not the generic BPABI version.  */
+ #undef  LINK_SPEC
+-#define LINK_SPEC EABI_LINK_SPEC					\
++#define LINK_SPEC EABI_LINK_SPEC TARGET_FIX_V4BX_SPEC			\
+   LINUX_OR_ANDROID_LD (LINUX_TARGET_LINK_SPEC,				\
+ 		       LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
+ 
diff --git a/toolchain/gcc/patches-12.x/850-use_shared_libgcc.patch b/toolchain/gcc/patches-12.x/850-use_shared_libgcc.patch
new file mode 100644
index 0000000..7be30f3
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/850-use_shared_libgcc.patch
@@ -0,0 +1,54 @@
+commit dcfc40358b5a3cae7320c17f8d1cebd5ad5540cd
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Feb 12 20:25:47 2012 +0000
+
+    gcc 4.6: port over the missing patch 850-use_shared_libgcc.patch to prevent libgcc crap from leaking into every single binary
+    
+    SVN-Revision: 30486
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -132,10 +132,6 @@
+   "%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s} "	\
+   LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+ 
+-/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
+-   do not use -lfloat.  */
+-#undef LIBGCC_SPEC
+-
+ /* Clear the instruction cache from `beg' to `end'.  This is
+    implemented in lib1funcs.S, so ensure an error if this definition
+    is used.  */
+--- a/gcc/config/linux.h
++++ b/gcc/config/linux.h
+@@ -71,6 +71,10 @@ see the files COPYING3 and COPYING.RUNTI
+ 	  builtin_version ("CRuntime_Musl");			\
+     } while (0)
+ 
++#ifndef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{static|static-libgcc:-lgcc}%{!static:%{!static-libgcc:-lgcc_s}}"
++#endif
++
+ /* Determine which dynamic linker to use depending on whether GLIBC or
+    uClibc or Bionic or musl is the default C library and whether
+    -muclibc or -mglibc or -mbionic or -mmusl has been passed to change
+--- a/libgcc/mkmap-symver.awk
++++ b/libgcc/mkmap-symver.awk
+@@ -136,5 +136,5 @@ function output(lib) {
+   else if (inherit[lib])
+     printf("} %s;\n", inherit[lib]);
+   else
+-    printf ("\n  local:\n\t*;\n};\n");
++    printf ("\n\t*;\n};\n");
+ }
+--- a/gcc/config/rs6000/linux.h
++++ b/gcc/config/rs6000/linux.h
+@@ -67,6 +67,9 @@
+ #undef	CPP_OS_DEFAULT_SPEC
+ #define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+ 
++#undef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{!static:%{!static-libgcc:-lgcc_s}} -lgcc"
++
+ #undef  LINK_SHLIB_SPEC
+ #define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}} \
+   %{static-pie:-static -pie --no-dynamic-linker -z text}"
diff --git a/toolchain/gcc/patches-12.x/851-libgcc_no_compat.patch b/toolchain/gcc/patches-12.x/851-libgcc_no_compat.patch
new file mode 100644
index 0000000..d710e40
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/851-libgcc_no_compat.patch
@@ -0,0 +1,22 @@
+commit 64661de100da1ec1061ef3e5e400285dce115e6b
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun May 10 13:16:35 2015 +0000
+
+    gcc: add some size optimization patches
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 45664
+
+--- a/libgcc/config/t-libunwind
++++ b/libgcc/config/t-libunwind
+@@ -2,8 +2,7 @@
+ 
+ HOST_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
+ 
+-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+-  $(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
++LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ 
+ # Override the default value from t-slibgcc-elf-ver and mention -lunwind
diff --git a/toolchain/gcc/patches-12.x/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches-12.x/870-ppc_no_crtsavres.patch
new file mode 100644
index 0000000..e51079d
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/870-ppc_no_crtsavres.patch
@@ -0,0 +1,11 @@
+--- a/gcc/config/rs6000/rs6000-logue.cc
++++ b/gcc/config/rs6000/rs6000-logue.cc
+@@ -348,7 +348,7 @@ rs6000_savres_strategy (rs6000_stack_t *
+   /* Define cutoff for using out-of-line functions to save registers.  */
+   if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
+     {
+-      if (!optimize_size)
++      if (1)
+ 	{
+ 	  strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ 	  strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
diff --git a/toolchain/gcc/patches-12.x/881-no_tm_section.patch b/toolchain/gcc/patches-12.x/881-no_tm_section.patch
new file mode 100644
index 0000000..2029910
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/881-no_tm_section.patch
@@ -0,0 +1,11 @@
+--- a/libgcc/crtstuff.c
++++ b/libgcc/crtstuff.c
+@@ -152,7 +152,7 @@ call_ ## FUNC (void)					\
+ #endif
+ 
+ #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF)
+-# define USE_TM_CLONE_REGISTRY 1
++# define USE_TM_CLONE_REGISTRY 0
+ #elif !defined(USE_TM_CLONE_REGISTRY)
+ # define USE_TM_CLONE_REGISTRY 0
+ #endif
diff --git a/toolchain/gcc/patches-12.x/900-bad-mips16-crt.patch b/toolchain/gcc/patches-12.x/900-bad-mips16-crt.patch
new file mode 100644
index 0000000..dd6e9dc
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/900-bad-mips16-crt.patch
@@ -0,0 +1,9 @@
+--- a/libgcc/config/mips/t-mips16
++++ b/libgcc/config/mips/t-mips16
+@@ -43,3 +43,6 @@ SYNC_CFLAGS = -mno-mips16
+ 
+ # Version these symbols if building libgcc.so.
+ SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver
++
++CRTSTUFF_T_CFLAGS += -mno-mips16
++CRTSTUFF_T_CFLAGS_S += -mno-mips16
diff --git a/toolchain/gcc/patches-12.x/910-mbsd_multi.patch b/toolchain/gcc/patches-12.x/910-mbsd_multi.patch
new file mode 100644
index 0000000..9233c6a
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/910-mbsd_multi.patch
@@ -0,0 +1,146 @@
+commit 99368862e44740ff4fd33760893f04e14f9dbdf1
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Jul 31 00:52:27 2007 +0000
+
+    Port the mbsd_multi patch from freewrt, which adds -fhonour-copts. This will emit warnings in packages that don't use our target cflags properly
+    
+    SVN-Revision: 8256
+
+	This patch brings over a feature from MirBSD:
+	* -fhonour-copts
+	  If this option is not given, it's warned (depending
+	  on environment variables). This is to catch errors
+	  of misbuilt packages which override CFLAGS themselves.
+
+	This patch was authored by Thorsten Glaser <tg at mirbsd.de>
+	with copyright assignment to the FSF in effect.
+
+--- a/gcc/c-family/c-opts.cc
++++ b/gcc/c-family/c-opts.cc
+@@ -107,6 +107,9 @@ static dump_flags_t original_dump_flags;
+ /* Whether any standard preincluded header has been preincluded.  */
+ static bool done_preinclude;
+ 
++/* Check if a port honours COPTS.  */
++static int honour_copts = 0;
++
+ static void handle_OPT_d (const char *);
+ static void set_std_cxx98 (int);
+ static void set_std_cxx11 (int);
+@@ -478,6 +481,12 @@ c_common_handle_option (size_t scode, co
+       flag_no_builtin = !value;
+       break;
+ 
++    case OPT_fhonour_copts:
++      if (c_language == clk_c) {
++        honour_copts++;
++      }
++      break;
++
+     case OPT_fconstant_string_class_:
+       constant_string_class_name = arg;
+       break;
+@@ -1218,6 +1227,47 @@ c_common_init (void)
+       return false;
+     }
+ 
++  if (c_language == clk_c) {
++    char *ev = getenv ("GCC_HONOUR_COPTS");
++    int evv;
++    if (ev == NULL)
++      evv = -1;
++    else if ((*ev == '0') || (*ev == '\0'))
++      evv = 0;
++    else if (*ev == '1')
++      evv = 1;
++    else if (*ev == '2')
++      evv = 2;
++    else if (*ev == 's')
++      evv = -1;
++    else {
++      warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1");
++      evv = 1; /* maybe depend this on something like MIRBSD_NATIVE?  */
++    }
++    if (evv == 1) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in lenient mode");
++        return false;
++      } else if (honour_copts != 1) {
++        warning (0, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++      }
++    } else if (evv == 2) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in strict mode");
++        return false;
++      } else if (honour_copts != 1) {
++        error ("someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++        return false;
++      }
++    } else if (evv == 0) {
++      if (honour_copts != 1)
++        inform (UNKNOWN_LOCATION, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++    }
++  }
++
+   return true;
+ }
+ 
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -1755,6 +1755,9 @@ C++ ObjC++ Optimization Alias(fexception
+ fhonor-std
+ C++ ObjC++ WarnRemoved
+ 
++fhonour-copts
++C ObjC C++ ObjC++ RejectNegative
++
+ fhosted
+ C ObjC
+ Assume normal C execution environment.
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1770,6 +1770,9 @@ fharden-conditional-branches
+ Common Var(flag_harden_conditional_branches) Optimization
+ Harden conditional branches by checking reversed conditions.
+ 
++fhonour-copts
++Common RejectNegative
++
+ ; Nonzero means ignore `#ident' directives.  0 means handle them.
+ ; Generate position-independent code for executables if possible
+ ; On SVR4 targets, it also controls whether or not to emit a
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -9597,6 +9597,17 @@ This option is only supported for C and
+ @option{-Wall} and by @option{-Wpedantic}, which can be disabled with
+ @option{-Wno-pointer-sign}.
+ 
++@item -fhonour-copts
++@opindex fhonour-copts
++If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not
++given at least once, and warn if it is given more than once.
++If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not
++given exactly once.
++If @env{GCC_HONOUR_COPTS} is set to 0 or unset, warn if this option
++is not given exactly once.
++The warning is quelled if @env{GCC_HONOUR_COPTS} is set to @samp{s}.
++This flag and environment variable only affect the C language.
++
+ @item -Wstack-protector
+ @opindex Wstack-protector
+ @opindex Wno-stack-protector
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2699,6 +2699,9 @@ common_handle_option (struct gcc_options
+       add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, arg);
+       break;
+ 
++    case OPT_fhonour_copts:
++      break;
++
+     case OPT_Werror:
+       dc->warning_as_error_requested = value;
+       break;
diff --git a/toolchain/gcc/patches-12.x/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches-12.x/920-specs_nonfatal_getenv.patch
new file mode 100644
index 0000000..59bd350
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/920-specs_nonfatal_getenv.patch
@@ -0,0 +1,22 @@
+Author: Jo-Philipp Wich <jow@openwrt.org>
+Date:   Sat Apr 21 03:02:39 2012 +0000
+
+    gcc: add patch to make the getenv() spec function nonfatal if requested environment variable is unset
+    
+    SVN-Revision: 31390
+
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -10186,8 +10186,10 @@ getenv_spec_function (int argc, const ch
+     }
+ 
+   if (!value)
+-    fatal_error (input_location,
+-		 "environment variable %qs not defined", varname);
++    {
++      warning (input_location, "environment variable %qs not defined", varname);
++      value = "";
++    }
+ 
+   /* We have to escape every character of the environment variable so
+      they are not interpreted as active spec characters.  A
diff --git a/toolchain/gcc/patches-12.x/960-gotools-fix-compilation-when-making-cross-compiler.patch b/toolchain/gcc/patches-12.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
new file mode 100644
index 0000000..b1d7576
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
@@ -0,0 +1,67 @@
+From dda6b050cd74a352670787a294596a9c56c21327 Mon Sep 17 00:00:00 2001
+From: Yousong Zhou <yszhou4tech@gmail.com>
+Date: Fri, 4 May 2018 18:20:53 +0800
+Subject: [PATCH] gotools: fix compilation when making cross compiler
+
+libgo is "the runtime support library for the Go programming language.
+This library is intended for use with the Go frontend."
+
+gccgo will link target files with libgo.so which depends on libgcc_s.so.1, but
+the linker will complain that it cannot find it.  That's because shared libgcc
+is not present in the install directory yet.  libgo.so was made without problem
+because gcc will emit -lgcc_s when compiled with -shared option.  When gotools
+were being made, it was supplied with -static-libgcc thus no link option was
+provided.  Check LIBGO in gcc/go/gcc-spec.c for how gccgo make a builtin spec
+for linking with libgo.so
+
+- GccgoCrossCompilation, https://github.com/golang/go/wiki/GccgoCrossCompilation
+- Cross-building instructions, http://www.eglibc.org/archives/patches/msg00078.html
+
+When 3-pass GCC compilation is used, shared libgcc runtime libraries will be
+available after gcc pass2 completed and will meet the gotools link requirement
+at gcc pass3
+---
+ gotools/Makefile.am | 4 +++-
+ gotools/Makefile.in | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/gotools/Makefile.am
++++ b/gotools/Makefile.am
+@@ -26,6 +26,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ 
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ 
+ LIBGOTOOL = $(libgodir)/libgotool.a
+@@ -41,7 +42,8 @@ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ 
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ 
+ libgosrcdir = $(srcdir)/../libgo/go
+--- a/gotools/Makefile.in
++++ b/gotools/Makefile.in
+@@ -337,6 +337,7 @@ mkinstalldirs = $(SHELL) $(toplevel_srcd
+ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ LIBGOTOOL = $(libgodir)/libgotool.a
+ @NATIVE_FALSE@GOCOMPILER = $(GOC)
+@@ -346,7 +347,8 @@ LIBGOTOOL = $(libgodir)/libgotool.a
+ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ libgosrcdir = $(srcdir)/../libgo/go
+ cmdsrcdir = $(libgosrcdir)/cmd
diff --git a/toolchain/gcc/patches-12.x/970-macos_arm64-building-fix.patch b/toolchain/gcc/patches-12.x/970-macos_arm64-building-fix.patch
new file mode 100644
index 0000000..8973044
--- /dev/null
+++ b/toolchain/gcc/patches-12.x/970-macos_arm64-building-fix.patch
@@ -0,0 +1,45 @@
+commit 9c6e71079b46ad5433165feaa2001450f2017b56
+Author: Przemysław Buczkowski <prem@prem.moe>
+Date:   Mon Aug 16 13:16:21 2021 +0100
+
+    GCC: Patch for Apple Silicon compatibility
+    
+    This patch fixes a linker error occuring when compiling
+    the cross-compiler on macOS and ARM64 architecture.
+    
+    Adapted from:
+    https://github.com/richfelker/musl-cross-make/issues/116#issuecomment-823612404
+    
+    Change-Id: Ia3ee98a163bbb62689f42e2da83a5ef36beb0913
+    Reviewed-on: https://review.haiku-os.org/c/buildtools/+/4329
+    Reviewed-by: John Scipione <jscipione@gmail.com>
+    Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
+
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -1293,7 +1293,7 @@ extern const char *aarch64_rewrite_mcpu
+ #define MCPU_TO_MARCH_SPEC_FUNCTIONS \
+   { "rewrite_mcpu", aarch64_rewrite_mcpu },
+ 
+-#if defined(__aarch64__)
++#if defined(__aarch64__) && ! defined(__APPLE__)
+ extern const char *host_detect_local_cpu (int argc, const char **argv);
+ #define HAVE_LOCAL_CPU_DETECT
+ # define EXTRA_SPEC_FUNCTIONS						\
+--- a/gcc/config/host-darwin.cc
++++ b/gcc/config/host-darwin.cc
+@@ -23,6 +23,8 @@
+ #include "options.h"
+ #include "diagnostic-core.h"
+ #include "config/host-darwin.h"
++#include "hosthooks.h"
++#include "hosthooks-def.h"
+ #include <errno.h>
+ 
+ /* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the
+@@ -181,3 +183,5 @@ darwin_gt_pch_use_address (void *&addr,
+ 
+   return 1;
+ }
++
++const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/toolchain/gcc/patches-13.x/002-case_insensitive.patch b/toolchain/gcc/patches-13.x/002-case_insensitive.patch
new file mode 100644
index 0000000..409497e
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/002-case_insensitive.patch
@@ -0,0 +1,24 @@
+commit 81cc26c706b2bc8c8c1eb1a322e5c5157900836e
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Oct 19 21:45:51 2014 +0000
+
+    gcc: do not assume that the Mac OS X filesystem is case insensitive
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 42973
+
+--- a/include/filenames.h
++++ b/include/filenames.h
+@@ -44,11 +44,6 @@ extern "C" {
+ #  define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f)
+ #else /* not DOSish */
+-#  if defined(__APPLE__)
+-#    ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+-#      define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
+-#    endif
+-#  endif /* __APPLE__ */
+ #  define HAS_DRIVE_SPEC(f) (0)
+ #  define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f)
diff --git a/toolchain/gcc/patches-13.x/010-documentation.patch b/toolchain/gcc/patches-13.x/010-documentation.patch
new file mode 100644
index 0000000..9646568
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/010-documentation.patch
@@ -0,0 +1,35 @@
+commit 098bd91f5eae625c7d2ee621e10930fc4434e5e2
+Author: Luka Perkov <luka@openwrt.org>
+Date:   Tue Feb 26 16:16:33 2013 +0000
+
+    gcc: don't build documentation
+    
+    This closes #13039.
+    
+    Signed-off-by: Luka Perkov <luka@openwrt.org>
+    
+    SVN-Revision: 35807
+
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -3397,18 +3397,10 @@ doc/gcc.info: $(TEXI_GCC_FILES)
+ doc/gccint.info: $(TEXI_GCCINT_FILES)
+ doc/cppinternals.info: $(TEXI_CPPINT_FILES)
+ 
+-doc/%.info: %.texi
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I . -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/%.info:
+ 
+ # Duplicate entry to handle renaming of gccinstall.info
+-doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/gccinstall.info:
+ 
+ doc/cpp.dvi: $(TEXI_CPP_FILES)
+ doc/gcc.dvi: $(TEXI_GCC_FILES)
diff --git a/toolchain/gcc/patches-13.x/110-Fix-MIPS-PR-84790.patch b/toolchain/gcc/patches-13.x/110-Fix-MIPS-PR-84790.patch
new file mode 100644
index 0000000..856fd6a
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/110-Fix-MIPS-PR-84790.patch
@@ -0,0 +1,20 @@
+Fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84790.
+MIPS16 functions have a static assembler prologue which clobbers
+registers v0 and v1. Add these register clobbers to function call
+instructions.
+
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -3134,6 +3134,12 @@ mips_emit_call_insn (rtx pattern, rtx or
+       emit_insn (gen_update_got_version ());
+     }
+ 
++  if (TARGET_MIPS16 && TARGET_USE_GOT)
++    {
++      clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), MIPS16_PIC_TEMP);
++      clobber_reg (&CALL_INSN_FUNCTION_USAGE (insn), MIPS_PROLOGUE_TEMP (word_mode));
++    }
++
+   if (TARGET_MIPS16
+       && TARGET_EXPLICIT_RELOCS
+       && TARGET_CALL_CLOBBERED_GP)
diff --git a/toolchain/gcc/patches-13.x/230-musl_libssp.patch b/toolchain/gcc/patches-13.x/230-musl_libssp.patch
new file mode 100644
index 0000000..fee068e
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/230-musl_libssp.patch
@@ -0,0 +1,13 @@
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -972,7 +972,9 @@ proper position among the other output f
+ #endif
+ 
+ #ifndef LINK_SSP_SPEC
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if DEFAULT_LIBC == LIBC_MUSL
++#define LINK_SSP_SPEC "-lssp_nonshared"
++#elif defined(TARGET_LIBC_PROVIDES_SSP)
+ #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ 		       "|fstack-protector-strong|fstack-protector-explicit:}"
+ #else
diff --git a/toolchain/gcc/patches-13.x/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches-13.x/300-mips_Os_cpu_rtx_cost_model.patch
new file mode 100644
index 0000000..2ca42ad
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/300-mips_Os_cpu_rtx_cost_model.patch
@@ -0,0 +1,21 @@
+commit ecf7671b769fe96f7b5134be442089f8bdba55d2
+Author: Felix Fietkau <nbd@nbd.name>
+Date:   Thu Aug 4 20:29:45 2016 +0200
+
+gcc: add a patch to generate better code with Os on mips
+
+Also happens to reduce compressed code size a bit
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -20219,7 +20219,7 @@ mips_option_override (void)
+     flag_pcc_struct_return = 0;
+ 
+   /* Decide which rtx_costs structure to use.  */
+-  if (optimize_size)
++  if (0 && optimize_size)
+     mips_cost = &mips_rtx_cost_optimize_size;
+   else
+     mips_cost = &mips_rtx_cost_data[mips_tune];
diff --git a/toolchain/gcc/patches-13.x/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches-13.x/810-arm-softfloat-libgcc.patch
new file mode 100644
index 0000000..5c9d86a
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/810-arm-softfloat-libgcc.patch
@@ -0,0 +1,33 @@
+commit 8570c4be394cff7282f332f97da2ff569a927ddb
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 20:06:12 2011 +0000
+
+    fixup arm soft-float symbols
+    
+    SVN-Revision: 25325
+
+--- a/libgcc/config/arm/t-linux
++++ b/libgcc/config/arm/t-linux
+@@ -1,6 +1,10 @@
+ LIB1ASMSRC = arm/lib1funcs.S
+ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
+-	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3
++	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3 \
++	_arm_negdf2 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
++	_arm_fixdfsi _arm_fixunsdfsi _arm_truncdfsf2 \
++	_arm_negsf2 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
++	_arm_fixsfsi _arm_fixunssfsi
+ 
+ # Just for these, we omit the frame pointer since it makes such a big
+ # difference.
+--- a/gcc/config/arm/linux-elf.h
++++ b/gcc/config/arm/linux-elf.h
+@@ -58,8 +58,6 @@
+    %{shared:-lc} \
+    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+ 
+-#define LIBGCC_SPEC "%{mfloat-abi=soft*:-lfloat} -lgcc"
+-
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+ 
+ #define LINUX_TARGET_LINK_SPEC  "%{h*} \
diff --git a/toolchain/gcc/patches-13.x/820-libgcc_pic.patch b/toolchain/gcc/patches-13.x/820-libgcc_pic.patch
new file mode 100644
index 0000000..7d10298
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/820-libgcc_pic.patch
@@ -0,0 +1,44 @@
+commit c96312958c0621e72c9b32da5bc224ffe2161384
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Oct 19 23:26:09 2009 +0000
+
+    gcc: create a proper libgcc_pic.a static library for relinking (4.3.3+ for now, backport will follow)
+    
+    SVN-Revision: 18086
+
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -933,11 +933,12 @@ $(libgcov-driver-objects): %$(objext): $
+ 
+ # Static libraries.
+ libgcc.a: $(libgcc-objects)
++libgcc_pic.a: $(libgcc-s-objects)
+ libgcov.a: $(libgcov-objects)
+ libunwind.a: $(libunwind-objects)
+ libgcc_eh.a: $(libgcc-eh-objects)
+ 
+-libgcc.a libgcov.a libunwind.a libgcc_eh.a:
++libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a:
+ 	-rm -f $@
+ 
+ 	objects="$(objects)";					\
+@@ -961,7 +962,7 @@ all: libunwind.a
+ endif
+ 
+ ifeq ($(enable_shared),yes)
+-all: libgcc_eh.a libgcc_s$(SHLIB_EXT)
++all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT)
+ ifneq ($(LIBUNWIND),)
+ all: libunwind$(SHLIB_EXT)
+ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT)
+@@ -1167,6 +1168,10 @@ install-shared:
+ 	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 
++	$(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/
++	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++
+ 	$(subst @multilib_dir@,$(MULTIDIR),$(subst \
+ 		@shlib_base_name@,libgcc_s,$(subst \
+ 		@shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL))))
diff --git a/toolchain/gcc/patches-13.x/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches-13.x/840-armv4_pass_fix-v4bx_to_ld.patch
new file mode 100644
index 0000000..82935f3
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/840-armv4_pass_fix-v4bx_to_ld.patch
@@ -0,0 +1,28 @@
+commit 7edc8ca5456d9743dd0075eb3cc5b04f4f24c8cc
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 19:34:36 2011 +0000
+
+    add armv4 fixup patches
+    
+    SVN-Revision: 25322
+
+
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -88,10 +88,15 @@
+ #define MUSL_DYNAMIC_LINKER \
+   "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}%{mfdpic:-fdpic}.so.1"
+ 
++/* For armv4 we pass --fix-v4bx to linker to support EABI */
++#undef TARGET_FIX_V4BX_SPEC
++#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*"\
++  "|march=armv4|mcpu=fa526|mcpu=fa626:--fix-v4bx}"
++
+ /* At this point, bpabi.h will have clobbered LINK_SPEC.  We want to
+    use the GNU/Linux version, not the generic BPABI version.  */
+ #undef  LINK_SPEC
+-#define LINK_SPEC EABI_LINK_SPEC					\
++#define LINK_SPEC EABI_LINK_SPEC TARGET_FIX_V4BX_SPEC			\
+   LINUX_OR_ANDROID_LD (LINUX_TARGET_LINK_SPEC,				\
+ 		       LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
+ 
diff --git a/toolchain/gcc/patches-13.x/850-use_shared_libgcc.patch b/toolchain/gcc/patches-13.x/850-use_shared_libgcc.patch
new file mode 100644
index 0000000..f4505ee
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/850-use_shared_libgcc.patch
@@ -0,0 +1,54 @@
+commit dcfc40358b5a3cae7320c17f8d1cebd5ad5540cd
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Feb 12 20:25:47 2012 +0000
+
+    gcc 4.6: port over the missing patch 850-use_shared_libgcc.patch to prevent libgcc crap from leaking into every single binary
+    
+    SVN-Revision: 30486
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -129,10 +129,6 @@
+   "%{Ofast|ffast-math|funsafe-math-optimizations:%{!shared:crtfastmath.o%s}} "	\
+   LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+ 
+-/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
+-   do not use -lfloat.  */
+-#undef LIBGCC_SPEC
+-
+ /* Clear the instruction cache from `beg' to `end'.  This is
+    implemented in lib1funcs.S, so ensure an error if this definition
+    is used.  */
+--- a/gcc/config/linux.h
++++ b/gcc/config/linux.h
+@@ -58,6 +58,10 @@ see the files COPYING3 and COPYING.RUNTI
+ 	builtin_assert ("system=posix");			\
+     } while (0)
+ 
++#ifndef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{static|static-libgcc:-lgcc}%{!static:%{!static-libgcc:-lgcc_s}}"
++#endif
++
+ /* Determine which dynamic linker to use depending on whether GLIBC or
+    uClibc or Bionic or musl is the default C library and whether
+    -muclibc or -mglibc or -mbionic or -mmusl has been passed to change
+--- a/libgcc/mkmap-symver.awk
++++ b/libgcc/mkmap-symver.awk
+@@ -136,5 +136,5 @@ function output(lib) {
+   else if (inherit[lib])
+     printf("} %s;\n", inherit[lib]);
+   else
+-    printf ("\n  local:\n\t*;\n};\n");
++    printf ("\n\t*;\n};\n");
+ }
+--- a/gcc/config/rs6000/linux.h
++++ b/gcc/config/rs6000/linux.h
+@@ -67,6 +67,9 @@
+ #undef	CPP_OS_DEFAULT_SPEC
+ #define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+ 
++#undef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{!static:%{!static-libgcc:-lgcc_s}} -lgcc"
++
+ #undef  LINK_SHLIB_SPEC
+ #define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}} \
+   %{static-pie:-static -pie --no-dynamic-linker -z text}"
diff --git a/toolchain/gcc/patches-13.x/851-libgcc_no_compat.patch b/toolchain/gcc/patches-13.x/851-libgcc_no_compat.patch
new file mode 100644
index 0000000..d710e40
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/851-libgcc_no_compat.patch
@@ -0,0 +1,22 @@
+commit 64661de100da1ec1061ef3e5e400285dce115e6b
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun May 10 13:16:35 2015 +0000
+
+    gcc: add some size optimization patches
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 45664
+
+--- a/libgcc/config/t-libunwind
++++ b/libgcc/config/t-libunwind
+@@ -2,8 +2,7 @@
+ 
+ HOST_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
+ 
+-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+-  $(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
++LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ 
+ # Override the default value from t-slibgcc-elf-ver and mention -lunwind
diff --git a/toolchain/gcc/patches-13.x/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches-13.x/870-ppc_no_crtsavres.patch
new file mode 100644
index 0000000..0dca688
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/870-ppc_no_crtsavres.patch
@@ -0,0 +1,11 @@
+--- a/gcc/config/rs6000/rs6000-logue.cc
++++ b/gcc/config/rs6000/rs6000-logue.cc
+@@ -344,7 +344,7 @@ rs6000_savres_strategy (rs6000_stack_t *
+   /* Define cutoff for using out-of-line functions to save registers.  */
+   if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
+     {
+-      if (!optimize_size)
++      if (1)
+ 	{
+ 	  strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ 	  strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
diff --git a/toolchain/gcc/patches-13.x/881-no_tm_section.patch b/toolchain/gcc/patches-13.x/881-no_tm_section.patch
new file mode 100644
index 0000000..2029910
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/881-no_tm_section.patch
@@ -0,0 +1,11 @@
+--- a/libgcc/crtstuff.c
++++ b/libgcc/crtstuff.c
+@@ -152,7 +152,7 @@ call_ ## FUNC (void)					\
+ #endif
+ 
+ #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF)
+-# define USE_TM_CLONE_REGISTRY 1
++# define USE_TM_CLONE_REGISTRY 0
+ #elif !defined(USE_TM_CLONE_REGISTRY)
+ # define USE_TM_CLONE_REGISTRY 0
+ #endif
diff --git a/toolchain/gcc/patches-13.x/900-bad-mips16-crt.patch b/toolchain/gcc/patches-13.x/900-bad-mips16-crt.patch
new file mode 100644
index 0000000..dd6e9dc
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/900-bad-mips16-crt.patch
@@ -0,0 +1,9 @@
+--- a/libgcc/config/mips/t-mips16
++++ b/libgcc/config/mips/t-mips16
+@@ -43,3 +43,6 @@ SYNC_CFLAGS = -mno-mips16
+ 
+ # Version these symbols if building libgcc.so.
+ SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver
++
++CRTSTUFF_T_CFLAGS += -mno-mips16
++CRTSTUFF_T_CFLAGS_S += -mno-mips16
diff --git a/toolchain/gcc/patches-13.x/910-mbsd_multi.patch b/toolchain/gcc/patches-13.x/910-mbsd_multi.patch
new file mode 100644
index 0000000..4138e79
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/910-mbsd_multi.patch
@@ -0,0 +1,146 @@
+commit 99368862e44740ff4fd33760893f04e14f9dbdf1
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Jul 31 00:52:27 2007 +0000
+
+    Port the mbsd_multi patch from freewrt, which adds -fhonour-copts. This will emit warnings in packages that don't use our target cflags properly
+    
+    SVN-Revision: 8256
+
+	This patch brings over a feature from MirBSD:
+	* -fhonour-copts
+	  If this option is not given, it's warned (depending
+	  on environment variables). This is to catch errors
+	  of misbuilt packages which override CFLAGS themselves.
+
+	This patch was authored by Thorsten Glaser <tg at mirbsd.de>
+	with copyright assignment to the FSF in effect.
+
+--- a/gcc/c-family/c-opts.cc
++++ b/gcc/c-family/c-opts.cc
+@@ -104,6 +104,9 @@ static size_t include_cursor;
+ /* Whether any standard preincluded header has been preincluded.  */
+ static bool done_preinclude;
+ 
++/* Check if a port honours COPTS.  */
++static int honour_copts = 0;
++
+ static void handle_OPT_d (const char *);
+ static void set_std_cxx98 (int);
+ static void set_std_cxx11 (int);
+@@ -475,6 +478,12 @@ c_common_handle_option (size_t scode, co
+       flag_no_builtin = !value;
+       break;
+ 
++    case OPT_fhonour_copts:
++      if (c_language == clk_c) {
++        honour_copts++;
++      }
++      break;
++
+     case OPT_fconstant_string_class_:
+       constant_string_class_name = arg;
+       break;
+@@ -1228,6 +1237,47 @@ c_common_init (void)
+       return false;
+     }
+ 
++  if (c_language == clk_c) {
++    char *ev = getenv ("GCC_HONOUR_COPTS");
++    int evv;
++    if (ev == NULL)
++      evv = -1;
++    else if ((*ev == '0') || (*ev == '\0'))
++      evv = 0;
++    else if (*ev == '1')
++      evv = 1;
++    else if (*ev == '2')
++      evv = 2;
++    else if (*ev == 's')
++      evv = -1;
++    else {
++      warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1");
++      evv = 1; /* maybe depend this on something like MIRBSD_NATIVE?  */
++    }
++    if (evv == 1) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in lenient mode");
++        return false;
++      } else if (honour_copts != 1) {
++        warning (0, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++      }
++    } else if (evv == 2) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in strict mode");
++        return false;
++      } else if (honour_copts != 1) {
++        error ("someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++        return false;
++      }
++    } else if (evv == 0) {
++      if (honour_copts != 1)
++        inform (UNKNOWN_LOCATION, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++    }
++  }
++
+   return true;
+ }
+ 
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -1837,6 +1837,9 @@ C++ ObjC++ Optimization Alias(fexception
+ fhonor-std
+ C++ ObjC++ WarnRemoved
+ 
++fhonour-copts
++C ObjC C++ ObjC++ RejectNegative
++
+ fhosted
+ C ObjC
+ Assume normal C execution environment.
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1801,6 +1801,9 @@ fharden-conditional-branches
+ Common Var(flag_harden_conditional_branches) Optimization
+ Harden conditional branches by checking reversed conditions.
+ 
++fhonour-copts
++Common RejectNegative
++
+ ; Nonzero means ignore `#ident' directives.  0 means handle them.
+ ; Generate position-independent code for executables if possible
+ ; On SVR4 targets, it also controls whether or not to emit a
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -10065,6 +10065,17 @@ This option is only supported for C and
+ @option{-Wall} and by @option{-Wpedantic}, which can be disabled with
+ @option{-Wno-pointer-sign}.
+ 
++@item -fhonour-copts
++@opindex fhonour-copts
++If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not
++given at least once, and warn if it is given more than once.
++If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not
++given exactly once.
++If @env{GCC_HONOUR_COPTS} is set to 0 or unset, warn if this option
++is not given exactly once.
++The warning is quelled if @env{GCC_HONOUR_COPTS} is set to @samp{s}.
++This flag and environment variable only affect the C language.
++
+ @opindex Wstack-protector
+ @opindex Wno-stack-protector
+ @item -Wstack-protector
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2767,6 +2767,9 @@ common_handle_option (struct gcc_options
+       add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, arg);
+       break;
+ 
++    case OPT_fhonour_copts:
++      break;
++
+     case OPT_Werror:
+       dc->warning_as_error_requested = value;
+       break;
diff --git a/toolchain/gcc/patches-13.x/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches-13.x/920-specs_nonfatal_getenv.patch
new file mode 100644
index 0000000..265ca22
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/920-specs_nonfatal_getenv.patch
@@ -0,0 +1,22 @@
+Author: Jo-Philipp Wich <jow@openwrt.org>
+Date:   Sat Apr 21 03:02:39 2012 +0000
+
+    gcc: add patch to make the getenv() spec function nonfatal if requested environment variable is unset
+    
+    SVN-Revision: 31390
+
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -10174,8 +10174,10 @@ getenv_spec_function (int argc, const ch
+     }
+ 
+   if (!value)
+-    fatal_error (input_location,
+-		 "environment variable %qs not defined", varname);
++    {
++      warning (input_location, "environment variable %qs not defined", varname);
++      value = "";
++    }
+ 
+   /* We have to escape every character of the environment variable so
+      they are not interpreted as active spec characters.  A
diff --git a/toolchain/gcc/patches-13.x/960-gotools-fix-compilation-when-making-cross-compiler.patch b/toolchain/gcc/patches-13.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
new file mode 100644
index 0000000..b1d7576
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
@@ -0,0 +1,67 @@
+From dda6b050cd74a352670787a294596a9c56c21327 Mon Sep 17 00:00:00 2001
+From: Yousong Zhou <yszhou4tech@gmail.com>
+Date: Fri, 4 May 2018 18:20:53 +0800
+Subject: [PATCH] gotools: fix compilation when making cross compiler
+
+libgo is "the runtime support library for the Go programming language.
+This library is intended for use with the Go frontend."
+
+gccgo will link target files with libgo.so which depends on libgcc_s.so.1, but
+the linker will complain that it cannot find it.  That's because shared libgcc
+is not present in the install directory yet.  libgo.so was made without problem
+because gcc will emit -lgcc_s when compiled with -shared option.  When gotools
+were being made, it was supplied with -static-libgcc thus no link option was
+provided.  Check LIBGO in gcc/go/gcc-spec.c for how gccgo make a builtin spec
+for linking with libgo.so
+
+- GccgoCrossCompilation, https://github.com/golang/go/wiki/GccgoCrossCompilation
+- Cross-building instructions, http://www.eglibc.org/archives/patches/msg00078.html
+
+When 3-pass GCC compilation is used, shared libgcc runtime libraries will be
+available after gcc pass2 completed and will meet the gotools link requirement
+at gcc pass3
+---
+ gotools/Makefile.am | 4 +++-
+ gotools/Makefile.in | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/gotools/Makefile.am
++++ b/gotools/Makefile.am
+@@ -26,6 +26,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ 
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ 
+ LIBGOTOOL = $(libgodir)/libgotool.a
+@@ -41,7 +42,8 @@ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ 
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ 
+ libgosrcdir = $(srcdir)/../libgo/go
+--- a/gotools/Makefile.in
++++ b/gotools/Makefile.in
+@@ -337,6 +337,7 @@ mkinstalldirs = $(SHELL) $(toplevel_srcd
+ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ LIBGOTOOL = $(libgodir)/libgotool.a
+ @NATIVE_FALSE@GOCOMPILER = $(GOC)
+@@ -346,7 +347,8 @@ LIBGOTOOL = $(libgodir)/libgotool.a
+ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ libgosrcdir = $(srcdir)/../libgo/go
+ cmdsrcdir = $(libgosrcdir)/cmd
diff --git a/toolchain/gcc/patches-13.x/970-macos_arm64-building-fix.patch b/toolchain/gcc/patches-13.x/970-macos_arm64-building-fix.patch
new file mode 100644
index 0000000..a0470b1
--- /dev/null
+++ b/toolchain/gcc/patches-13.x/970-macos_arm64-building-fix.patch
@@ -0,0 +1,45 @@
+commit 9c6e71079b46ad5433165feaa2001450f2017b56
+Author: Przemysław Buczkowski <prem@prem.moe>
+Date:   Mon Aug 16 13:16:21 2021 +0100
+
+    GCC: Patch for Apple Silicon compatibility
+    
+    This patch fixes a linker error occuring when compiling
+    the cross-compiler on macOS and ARM64 architecture.
+    
+    Adapted from:
+    https://github.com/richfelker/musl-cross-make/issues/116#issuecomment-823612404
+    
+    Change-Id: Ia3ee98a163bbb62689f42e2da83a5ef36beb0913
+    Reviewed-on: https://review.haiku-os.org/c/buildtools/+/4329
+    Reviewed-by: John Scipione <jscipione@gmail.com>
+    Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
+
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -1195,7 +1195,7 @@ extern enum aarch64_code_model aarch64_c
+ 
+ /* Extra specs when building a native AArch64-hosted compiler.
+    Option rewriting rules based on host system.  */
+-#if defined(__aarch64__)
++#if defined(__aarch64__) && ! defined(__APPLE__)
+ extern const char *host_detect_local_cpu (int argc, const char **argv);
+ #define HAVE_LOCAL_CPU_DETECT
+ # define EXTRA_SPEC_FUNCTIONS                                           \
+--- a/gcc/config/host-darwin.cc
++++ b/gcc/config/host-darwin.cc
+@@ -23,6 +23,8 @@
+ #include "options.h"
+ #include "diagnostic-core.h"
+ #include "config/host-darwin.h"
++#include "hosthooks.h"
++#include "hosthooks-def.h"
+ #include <errno.h>
+ 
+ /* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the
+@@ -181,3 +183,5 @@ darwin_gt_pch_use_address (void *&addr,
+ 
+   return 1;
+ }
++
++const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/toolchain/gcc/patches-14.x/002-case_insensitive.patch b/toolchain/gcc/patches-14.x/002-case_insensitive.patch
new file mode 100644
index 0000000..409497e
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/002-case_insensitive.patch
@@ -0,0 +1,24 @@
+commit 81cc26c706b2bc8c8c1eb1a322e5c5157900836e
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Oct 19 21:45:51 2014 +0000
+
+    gcc: do not assume that the Mac OS X filesystem is case insensitive
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 42973
+
+--- a/include/filenames.h
++++ b/include/filenames.h
+@@ -44,11 +44,6 @@ extern "C" {
+ #  define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f)
+ #else /* not DOSish */
+-#  if defined(__APPLE__)
+-#    ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+-#      define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
+-#    endif
+-#  endif /* __APPLE__ */
+ #  define HAS_DRIVE_SPEC(f) (0)
+ #  define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c)
+ #  define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f)
diff --git a/toolchain/gcc/patches-14.x/003-dont-choke-when-building-32bit-on-64bit.patch b/toolchain/gcc/patches-14.x/003-dont-choke-when-building-32bit-on-64bit.patch
new file mode 100644
index 0000000..c41f35e
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/003-dont-choke-when-building-32bit-on-64bit.patch
@@ -0,0 +1,13 @@
+--- a/gcc/real.h
++++ b/gcc/real.h
+@@ -77,8 +77,10 @@ struct GTY(()) real_value {
+    + (REAL_VALUE_TYPE_SIZE%HOST_BITS_PER_WIDE_INT ? 1 : 0)) /* round up */
+ 
+ /* Verify the guess.  */
++#ifndef __LP64__
+ extern char test_real_width
+   [sizeof (REAL_VALUE_TYPE) <= REAL_WIDTH * sizeof (HOST_WIDE_INT) ? 1 : -1];
++#endif
+ 
+ /* Calculate the format for CONST_DOUBLE.  We need as many slots as
+    are necessary to overlay a REAL_VALUE_TYPE on them.  This could be
diff --git a/toolchain/gcc/patches-14.x/010-documentation.patch b/toolchain/gcc/patches-14.x/010-documentation.patch
new file mode 100644
index 0000000..7cf59d3
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/010-documentation.patch
@@ -0,0 +1,35 @@
+commit 098bd91f5eae625c7d2ee621e10930fc4434e5e2
+Author: Luka Perkov <luka@openwrt.org>
+Date:   Tue Feb 26 16:16:33 2013 +0000
+
+    gcc: don't build documentation
+    
+    This closes #13039.
+    
+    Signed-off-by: Luka Perkov <luka@openwrt.org>
+    
+    SVN-Revision: 35807
+
+--- a/gcc/Makefile.in
++++ b/gcc/Makefile.in
+@@ -3549,18 +3549,10 @@ doc/gcc.info: $(TEXI_GCC_FILES)
+ doc/gccint.info: $(TEXI_GCCINT_FILES)
+ doc/cppinternals.info: $(TEXI_CPPINT_FILES)
+ 
+-doc/%.info: %.texi
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I . -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/%.info:
+ 
+ # Duplicate entry to handle renaming of gccinstall.info
+-doc/gccinstall.info: $(TEXI_GCCINSTALL_FILES)
+-	if [ x$(BUILD_INFO) = xinfo ]; then \
+-		$(MAKEINFO) $(MAKEINFOFLAGS) -I $(gcc_docdir) \
+-			-I $(gcc_docdir)/include -o $@ $<; \
+-	fi
++doc/gccinstall.info:
+ 
+ doc/cpp.dvi: $(TEXI_CPP_FILES)
+ doc/gcc.dvi: $(TEXI_GCC_FILES)
diff --git a/toolchain/gcc/patches-14.x/230-musl_libssp.patch b/toolchain/gcc/patches-14.x/230-musl_libssp.patch
new file mode 100644
index 0000000..3ce5e49
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/230-musl_libssp.patch
@@ -0,0 +1,13 @@
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -985,7 +985,9 @@ proper position among the other output f
+ #endif
+ 
+ #ifndef LINK_SSP_SPEC
+-#ifdef TARGET_LIBC_PROVIDES_SSP
++#if DEFAULT_LIBC == LIBC_MUSL
++#define LINK_SSP_SPEC "-lssp_nonshared"
++#elif defined(TARGET_LIBC_PROVIDES_SSP)
+ #define LINK_SSP_SPEC "%{fstack-protector|fstack-protector-all" \
+ 		       "|fstack-protector-strong|fstack-protector-explicit:}"
+ #else
diff --git a/toolchain/gcc/patches-14.x/300-mips_Os_cpu_rtx_cost_model.patch b/toolchain/gcc/patches-14.x/300-mips_Os_cpu_rtx_cost_model.patch
new file mode 100644
index 0000000..2cbffe4
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/300-mips_Os_cpu_rtx_cost_model.patch
@@ -0,0 +1,21 @@
+commit ecf7671b769fe96f7b5134be442089f8bdba55d2
+Author: Felix Fietkau <nbd@nbd.name>
+Date:   Thu Aug 4 20:29:45 2016 +0200
+
+gcc: add a patch to generate better code with Os on mips
+
+Also happens to reduce compressed code size a bit
+
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+
+--- a/gcc/config/mips/mips.cc
++++ b/gcc/config/mips/mips.cc
+@@ -20453,7 +20453,7 @@ mips_option_override (void)
+     flag_pcc_struct_return = 0;
+ 
+   /* Decide which rtx_costs structure to use.  */
+-  if (optimize_size)
++  if (0 && optimize_size)
+     mips_cost = &mips_rtx_cost_optimize_size;
+   else
+     mips_cost = &mips_rtx_cost_data[mips_tune];
diff --git a/toolchain/gcc/patches-14.x/810-arm-softfloat-libgcc.patch b/toolchain/gcc/patches-14.x/810-arm-softfloat-libgcc.patch
new file mode 100644
index 0000000..5c9d86a
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/810-arm-softfloat-libgcc.patch
@@ -0,0 +1,33 @@
+commit 8570c4be394cff7282f332f97da2ff569a927ddb
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 20:06:12 2011 +0000
+
+    fixup arm soft-float symbols
+    
+    SVN-Revision: 25325
+
+--- a/libgcc/config/arm/t-linux
++++ b/libgcc/config/arm/t-linux
+@@ -1,6 +1,10 @@
+ LIB1ASMSRC = arm/lib1funcs.S
+ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx _clzsi2 _clzdi2 \
+-	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3
++	_ctzsi2 _arm_addsubdf3 _arm_addsubsf3 \
++	_arm_negdf2 _arm_muldivdf3 _arm_cmpdf2 _arm_unorddf2 \
++	_arm_fixdfsi _arm_fixunsdfsi _arm_truncdfsf2 \
++	_arm_negsf2 _arm_muldivsf3 _arm_cmpsf2 _arm_unordsf2 \
++	_arm_fixsfsi _arm_fixunssfsi
+ 
+ # Just for these, we omit the frame pointer since it makes such a big
+ # difference.
+--- a/gcc/config/arm/linux-elf.h
++++ b/gcc/config/arm/linux-elf.h
+@@ -58,8 +58,6 @@
+    %{shared:-lc} \
+    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
+ 
+-#define LIBGCC_SPEC "%{mfloat-abi=soft*:-lfloat} -lgcc"
+-
+ #define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+ 
+ #define LINUX_TARGET_LINK_SPEC  "%{h*} \
diff --git a/toolchain/gcc/patches-14.x/820-libgcc_pic.patch b/toolchain/gcc/patches-14.x/820-libgcc_pic.patch
new file mode 100644
index 0000000..3ab73f4
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/820-libgcc_pic.patch
@@ -0,0 +1,44 @@
+commit c96312958c0621e72c9b32da5bc224ffe2161384
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Mon Oct 19 23:26:09 2009 +0000
+
+    gcc: create a proper libgcc_pic.a static library for relinking (4.3.3+ for now, backport will follow)
+    
+    SVN-Revision: 18086
+
+--- a/libgcc/Makefile.in
++++ b/libgcc/Makefile.in
+@@ -940,11 +940,12 @@ $(libgcov-driver-objects): %$(objext): $
+ 
+ # Static libraries.
+ libgcc.a: $(libgcc-objects)
++libgcc_pic.a: $(libgcc-s-objects)
+ libgcov.a: $(libgcov-objects)
+ libunwind.a: $(libunwind-objects)
+ libgcc_eh.a: $(libgcc-eh-objects)
+ 
+-libgcc.a libgcov.a libunwind.a libgcc_eh.a:
++libgcc.a libgcov.a libunwind.a libgcc_eh.a libgcc_pic.a:
+ 	-rm -f $@
+ 
+ 	objects="$(objects)";					\
+@@ -968,7 +969,7 @@ all: libunwind.a
+ endif
+ 
+ ifeq ($(enable_shared),yes)
+-all: libgcc_eh.a libgcc_s$(SHLIB_EXT)
++all: libgcc_eh.a libgcc_pic.a libgcc_s$(SHLIB_EXT)
+ ifneq ($(LIBUNWIND),)
+ all: libunwind$(SHLIB_EXT)
+ libgcc_s$(SHLIB_EXT): libunwind$(SHLIB_EXT)
+@@ -1174,6 +1175,10 @@ install-shared:
+ 	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_eh.a
+ 
++	$(INSTALL_DATA) libgcc_pic.a $(mapfile) $(DESTDIR)$(inst_libdir)/
++	chmod 644 $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++	$(RANLIB) $(DESTDIR)$(inst_libdir)/libgcc_pic.a
++
+ 	$(subst @multilib_dir@,$(MULTIDIR),$(subst \
+ 		@shlib_base_name@,libgcc_s,$(subst \
+ 		@shlib_slibdir_qual@,$(MULTIOSSUBDIR),$(SHLIB_INSTALL))))
diff --git a/toolchain/gcc/patches-14.x/840-armv4_pass_fix-v4bx_to_ld.patch b/toolchain/gcc/patches-14.x/840-armv4_pass_fix-v4bx_to_ld.patch
new file mode 100644
index 0000000..82935f3
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/840-armv4_pass_fix-v4bx_to_ld.patch
@@ -0,0 +1,28 @@
+commit 7edc8ca5456d9743dd0075eb3cc5b04f4f24c8cc
+Author: Imre Kaloz <kaloz@openwrt.org>
+Date:   Wed Feb 2 19:34:36 2011 +0000
+
+    add armv4 fixup patches
+    
+    SVN-Revision: 25322
+
+
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -88,10 +88,15 @@
+ #define MUSL_DYNAMIC_LINKER \
+   "/lib/ld-musl-arm" MUSL_DYNAMIC_LINKER_E "%{mfloat-abi=hard:hf}%{mfdpic:-fdpic}.so.1"
+ 
++/* For armv4 we pass --fix-v4bx to linker to support EABI */
++#undef TARGET_FIX_V4BX_SPEC
++#define TARGET_FIX_V4BX_SPEC " %{mcpu=arm8|mcpu=arm810|mcpu=strongarm*"\
++  "|march=armv4|mcpu=fa526|mcpu=fa626:--fix-v4bx}"
++
+ /* At this point, bpabi.h will have clobbered LINK_SPEC.  We want to
+    use the GNU/Linux version, not the generic BPABI version.  */
+ #undef  LINK_SPEC
+-#define LINK_SPEC EABI_LINK_SPEC					\
++#define LINK_SPEC EABI_LINK_SPEC TARGET_FIX_V4BX_SPEC			\
+   LINUX_OR_ANDROID_LD (LINUX_TARGET_LINK_SPEC,				\
+ 		       LINUX_TARGET_LINK_SPEC " " ANDROID_LINK_SPEC)
+ 
diff --git a/toolchain/gcc/patches-14.x/850-use_shared_libgcc.patch b/toolchain/gcc/patches-14.x/850-use_shared_libgcc.patch
new file mode 100644
index 0000000..66926ed
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/850-use_shared_libgcc.patch
@@ -0,0 +1,54 @@
+commit dcfc40358b5a3cae7320c17f8d1cebd5ad5540cd
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun Feb 12 20:25:47 2012 +0000
+
+    gcc 4.6: port over the missing patch 850-use_shared_libgcc.patch to prevent libgcc crap from leaking into every single binary
+    
+    SVN-Revision: 30486
+--- a/gcc/config/arm/linux-eabi.h
++++ b/gcc/config/arm/linux-eabi.h
+@@ -129,10 +129,6 @@
+   "%{Ofast|ffast-math|funsafe-math-optimizations:%{!shared:crtfastmath.o%s}} "	\
+   LINUX_OR_ANDROID_LD (GNU_USER_TARGET_ENDFILE_SPEC, ANDROID_ENDFILE_SPEC)
+ 
+-/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
+-   do not use -lfloat.  */
+-#undef LIBGCC_SPEC
+-
+ /* Clear the instruction cache from `beg' to `end'.  This is
+    implemented in lib1funcs.S, so ensure an error if this definition
+    is used.  */
+--- a/gcc/config/linux.h
++++ b/gcc/config/linux.h
+@@ -58,6 +58,10 @@ see the files COPYING3 and COPYING.RUNTI
+ 	builtin_assert ("system=posix");			\
+     } while (0)
+ 
++#ifndef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{static|static-libgcc:-lgcc}%{!static:%{!static-libgcc:-lgcc_s}}"
++#endif
++
+ /* Determine which dynamic linker to use depending on whether GLIBC or
+    uClibc or Bionic or musl is the default C library and whether
+    -muclibc or -mglibc or -mbionic or -mmusl has been passed to change
+--- a/libgcc/mkmap-symver.awk
++++ b/libgcc/mkmap-symver.awk
+@@ -136,5 +136,5 @@ function output(lib) {
+   else if (inherit[lib])
+     printf("} %s;\n", inherit[lib]);
+   else
+-    printf ("\n  local:\n\t*;\n};\n");
++    printf ("\n\t*;\n};\n");
+ }
+--- a/gcc/config/rs6000/linux.h
++++ b/gcc/config/rs6000/linux.h
+@@ -70,6 +70,9 @@
+ #undef	CPP_OS_DEFAULT_SPEC
+ #define CPP_OS_DEFAULT_SPEC "%(cpp_os_linux)"
+ 
++#undef LIBGCC_SPEC
++#define LIBGCC_SPEC "%{!static:%{!static-libgcc:-lgcc_s}} -lgcc"
++
+ #undef  LINK_SHLIB_SPEC
+ #define LINK_SHLIB_SPEC "%{shared:-shared} %{!shared: %{static:-static}} \
+   %{static-pie:-static -pie --no-dynamic-linker -z text}"
diff --git a/toolchain/gcc/patches-14.x/851-libgcc_no_compat.patch b/toolchain/gcc/patches-14.x/851-libgcc_no_compat.patch
new file mode 100644
index 0000000..d710e40
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/851-libgcc_no_compat.patch
@@ -0,0 +1,22 @@
+commit 64661de100da1ec1061ef3e5e400285dce115e6b
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Sun May 10 13:16:35 2015 +0000
+
+    gcc: add some size optimization patches
+    
+    Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+    
+    SVN-Revision: 45664
+
+--- a/libgcc/config/t-libunwind
++++ b/libgcc/config/t-libunwind
+@@ -2,8 +2,7 @@
+ 
+ HOST_LIBGCC2_CFLAGS += -DUSE_GAS_SYMVER
+ 
+-LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c \
+-  $(srcdir)/unwind-compat.c $(srcdir)/unwind-dw2-fde-compat.c
++LIB2ADDEH = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ LIB2ADDEHSTATIC = $(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
+ 
+ # Override the default value from t-slibgcc-elf-ver and mention -lunwind
diff --git a/toolchain/gcc/patches-14.x/870-ppc_no_crtsavres.patch b/toolchain/gcc/patches-14.x/870-ppc_no_crtsavres.patch
new file mode 100644
index 0000000..0dca688
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/870-ppc_no_crtsavres.patch
@@ -0,0 +1,11 @@
+--- a/gcc/config/rs6000/rs6000-logue.cc
++++ b/gcc/config/rs6000/rs6000-logue.cc
+@@ -344,7 +344,7 @@ rs6000_savres_strategy (rs6000_stack_t *
+   /* Define cutoff for using out-of-line functions to save registers.  */
+   if (DEFAULT_ABI == ABI_V4 || TARGET_ELF)
+     {
+-      if (!optimize_size)
++      if (1)
+ 	{
+ 	  strategy |= SAVE_INLINE_FPRS | REST_INLINE_FPRS;
+ 	  strategy |= SAVE_INLINE_GPRS | REST_INLINE_GPRS;
diff --git a/toolchain/gcc/patches-14.x/881-no_tm_section.patch b/toolchain/gcc/patches-14.x/881-no_tm_section.patch
new file mode 100644
index 0000000..2029910
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/881-no_tm_section.patch
@@ -0,0 +1,11 @@
+--- a/libgcc/crtstuff.c
++++ b/libgcc/crtstuff.c
+@@ -152,7 +152,7 @@ call_ ## FUNC (void)					\
+ #endif
+ 
+ #if !defined(USE_TM_CLONE_REGISTRY) && defined(OBJECT_FORMAT_ELF)
+-# define USE_TM_CLONE_REGISTRY 1
++# define USE_TM_CLONE_REGISTRY 0
+ #elif !defined(USE_TM_CLONE_REGISTRY)
+ # define USE_TM_CLONE_REGISTRY 0
+ #endif
diff --git a/toolchain/gcc/patches-14.x/900-bad-mips16-crt.patch b/toolchain/gcc/patches-14.x/900-bad-mips16-crt.patch
new file mode 100644
index 0000000..b355545
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/900-bad-mips16-crt.patch
@@ -0,0 +1,9 @@
+--- a/libgcc/config/mips/t-mips16
++++ b/libgcc/config/mips/t-mips16
+@@ -42,3 +42,6 @@ SYNC_CFLAGS = -mno-mips16
+ 
+ # Version these symbols if building libgcc.so.
+ SHLIB_MAPFILES += $(srcdir)/config/mips/libgcc-mips16.ver
++
++CRTSTUFF_T_CFLAGS += -mno-mips16
++CRTSTUFF_T_CFLAGS_S += -mno-mips16
diff --git a/toolchain/gcc/patches-14.x/910-mbsd_multi.patch b/toolchain/gcc/patches-14.x/910-mbsd_multi.patch
new file mode 100644
index 0000000..2a58df3
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/910-mbsd_multi.patch
@@ -0,0 +1,146 @@
+commit 99368862e44740ff4fd33760893f04e14f9dbdf1
+Author: Felix Fietkau <nbd@openwrt.org>
+Date:   Tue Jul 31 00:52:27 2007 +0000
+
+    Port the mbsd_multi patch from freewrt, which adds -fhonour-copts. This will emit warnings in packages that don't use our target cflags properly
+    
+    SVN-Revision: 8256
+
+	This patch brings over a feature from MirBSD:
+	* -fhonour-copts
+	  If this option is not given, it's warned (depending
+	  on environment variables). This is to catch errors
+	  of misbuilt packages which override CFLAGS themselves.
+
+	This patch was authored by Thorsten Glaser <tg at mirbsd.de>
+	with copyright assignment to the FSF in effect.
+
+--- a/gcc/c-family/c-opts.cc
++++ b/gcc/c-family/c-opts.cc
+@@ -108,6 +108,9 @@ static size_t include_cursor;
+ /* Whether any standard preincluded header has been preincluded.  */
+ static bool done_preinclude;
+ 
++/* Check if a port honours COPTS.  */
++static int honour_copts = 0;
++
+ static void handle_OPT_d (const char *);
+ static void set_std_cxx98 (int);
+ static void set_std_cxx11 (int);
+@@ -498,6 +501,12 @@ c_common_handle_option (size_t scode, co
+       flag_no_builtin = !value;
+       break;
+ 
++    case OPT_fhonour_copts:
++      if (c_language == clk_c) {
++        honour_copts++;
++      }
++      break;
++
+     case OPT_fconstant_string_class_:
+       constant_string_class_name = arg;
+       break;
+@@ -1291,6 +1300,47 @@ c_common_init (void)
+       return false;
+     }
+ 
++  if (c_language == clk_c) {
++    char *ev = getenv ("GCC_HONOUR_COPTS");
++    int evv;
++    if (ev == NULL)
++      evv = -1;
++    else if ((*ev == '0') || (*ev == '\0'))
++      evv = 0;
++    else if (*ev == '1')
++      evv = 1;
++    else if (*ev == '2')
++      evv = 2;
++    else if (*ev == 's')
++      evv = -1;
++    else {
++      warning (0, "unknown GCC_HONOUR_COPTS value, assuming 1");
++      evv = 1; /* maybe depend this on something like MIRBSD_NATIVE?  */
++    }
++    if (evv == 1) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in lenient mode");
++        return false;
++      } else if (honour_copts != 1) {
++        warning (0, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++      }
++    } else if (evv == 2) {
++      if (honour_copts == 0) {
++        error ("someone does not honour COPTS at all in strict mode");
++        return false;
++      } else if (honour_copts != 1) {
++        error ("someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++        return false;
++      }
++    } else if (evv == 0) {
++      if (honour_copts != 1)
++        inform (UNKNOWN_LOCATION, "someone does not honour COPTS correctly, passed %d times",
++         honour_copts);
++    }
++  }
++
+   return true;
+ }
+ 
+--- a/gcc/c-family/c.opt
++++ b/gcc/c-family/c.opt
+@@ -1910,6 +1910,9 @@ C++ ObjC++ Optimization Alias(fexception
+ fhonor-std
+ C++ ObjC++ WarnRemoved
+ 
++fhonour-copts
++C ObjC C++ ObjC++ RejectNegative
++
+ fhosted
+ C ObjC
+ Assume normal C execution environment.
+--- a/gcc/common.opt
++++ b/gcc/common.opt
+@@ -1881,6 +1881,9 @@ Enum(hardcfr_check_noreturn_calls) Strin
+ EnumValue
+ Enum(hardcfr_check_noreturn_calls) String(always) Value(HCFRNR_ALWAYS)
+ 
++fhonour-copts
++Common RejectNegative
++
+ ; Nonzero means ignore `#ident' directives.  0 means handle them.
+ ; Generate position-independent code for executables if possible
+ ; On SVR4 targets, it also controls whether or not to emit a
+--- a/gcc/doc/invoke.texi
++++ b/gcc/doc/invoke.texi
+@@ -10597,6 +10597,17 @@ This option is only supported for C and
+ 
+ This warning is upgraded to an error by @option{-pedantic-errors}.
+ 
++@item -fhonour-copts
++@opindex fhonour-copts
++If @env{GCC_HONOUR_COPTS} is set to 1, abort if this option is not
++given at least once, and warn if it is given more than once.
++If @env{GCC_HONOUR_COPTS} is set to 2, abort if this option is not
++given exactly once.
++If @env{GCC_HONOUR_COPTS} is set to 0 or unset, warn if this option
++is not given exactly once.
++The warning is quelled if @env{GCC_HONOUR_COPTS} is set to @samp{s}.
++This flag and environment variable only affect the C language.
++
+ @opindex Wstack-protector
+ @opindex Wno-stack-protector
+ @item -Wstack-protector
+--- a/gcc/opts.cc
++++ b/gcc/opts.cc
+@@ -2833,6 +2833,9 @@ common_handle_option (struct gcc_options
+       add_comma_separated_to_vector (&opts->x_flag_ignored_attributes, arg);
+       break;
+ 
++    case OPT_fhonour_copts:
++      break;
++
+     case OPT_Werror:
+       dc->set_warning_as_error_requested (value);
+       break;
diff --git a/toolchain/gcc/patches-14.x/920-specs_nonfatal_getenv.patch b/toolchain/gcc/patches-14.x/920-specs_nonfatal_getenv.patch
new file mode 100644
index 0000000..121b684
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/920-specs_nonfatal_getenv.patch
@@ -0,0 +1,22 @@
+Author: Jo-Philipp Wich <jow@openwrt.org>
+Date:   Sat Apr 21 03:02:39 2012 +0000
+
+    gcc: add patch to make the getenv() spec function nonfatal if requested environment variable is unset
+    
+    SVN-Revision: 31390
+
+--- a/gcc/gcc.cc
++++ b/gcc/gcc.cc
+@@ -10319,8 +10319,10 @@ getenv_spec_function (int argc, const ch
+     }
+ 
+   if (!value)
+-    fatal_error (input_location,
+-		 "environment variable %qs not defined", varname);
++    {
++      warning (input_location, "environment variable %qs not defined", varname);
++      value = "";
++    }
+ 
+   /* We have to escape every character of the environment variable so
+      they are not interpreted as active spec characters.  A
diff --git a/toolchain/gcc/patches-14.x/960-gotools-fix-compilation-when-making-cross-compiler.patch b/toolchain/gcc/patches-14.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
new file mode 100644
index 0000000..b1d7576
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/960-gotools-fix-compilation-when-making-cross-compiler.patch
@@ -0,0 +1,67 @@
+From dda6b050cd74a352670787a294596a9c56c21327 Mon Sep 17 00:00:00 2001
+From: Yousong Zhou <yszhou4tech@gmail.com>
+Date: Fri, 4 May 2018 18:20:53 +0800
+Subject: [PATCH] gotools: fix compilation when making cross compiler
+
+libgo is "the runtime support library for the Go programming language.
+This library is intended for use with the Go frontend."
+
+gccgo will link target files with libgo.so which depends on libgcc_s.so.1, but
+the linker will complain that it cannot find it.  That's because shared libgcc
+is not present in the install directory yet.  libgo.so was made without problem
+because gcc will emit -lgcc_s when compiled with -shared option.  When gotools
+were being made, it was supplied with -static-libgcc thus no link option was
+provided.  Check LIBGO in gcc/go/gcc-spec.c for how gccgo make a builtin spec
+for linking with libgo.so
+
+- GccgoCrossCompilation, https://github.com/golang/go/wiki/GccgoCrossCompilation
+- Cross-building instructions, http://www.eglibc.org/archives/patches/msg00078.html
+
+When 3-pass GCC compilation is used, shared libgcc runtime libraries will be
+available after gcc pass2 completed and will meet the gotools link requirement
+at gcc pass3
+---
+ gotools/Makefile.am | 4 +++-
+ gotools/Makefile.in | 4 +++-
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/gotools/Makefile.am
++++ b/gotools/Makefile.am
+@@ -26,6 +26,7 @@ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ 
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ 
+ LIBGOTOOL = $(libgodir)/libgotool.a
+@@ -41,7 +42,8 @@ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ 
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ 
+ libgosrcdir = $(srcdir)/../libgo/go
+--- a/gotools/Makefile.in
++++ b/gotools/Makefile.in
+@@ -337,6 +337,7 @@ mkinstalldirs = $(SHELL) $(toplevel_srcd
+ PWD_COMMAND = $${PWDCMD-pwd}
+ STAMP = echo timestamp >
+ libgodir = ../$(target_noncanonical)/libgo
++libgccdir = ../$(target_noncanonical)/libgcc
+ LIBGODEP = $(libgodir)/libgo.la
+ LIBGOTOOL = $(libgodir)/libgotool.a
+ @NATIVE_FALSE@GOCOMPILER = $(GOC)
+@@ -346,7 +347,8 @@ LIBGOTOOL = $(libgodir)/libgotool.a
+ GOCFLAGS = $(CFLAGS_FOR_TARGET)
+ GOCOMPILE = $(GOCOMPILER) $(GOCFLAGS)
+ AM_GOCFLAGS = -I $(libgodir)
+-AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs
++AM_LDFLAGS = -L $(libgodir) -L $(libgodir)/.libs \
++	-L $(libgccdir) -L $(libgccdir)/.libs -lgcc_s
+ GOLINK = $(GOCOMPILER) $(GOCFLAGS) $(AM_GOCFLAGS) $(LDFLAGS) $(AM_LDFLAGS) -o $@
+ libgosrcdir = $(srcdir)/../libgo/go
+ cmdsrcdir = $(libgosrcdir)/cmd
diff --git a/toolchain/gcc/patches-14.x/970-macos_arm64-building-fix.patch b/toolchain/gcc/patches-14.x/970-macos_arm64-building-fix.patch
new file mode 100644
index 0000000..da878df
--- /dev/null
+++ b/toolchain/gcc/patches-14.x/970-macos_arm64-building-fix.patch
@@ -0,0 +1,45 @@
+commit 9c6e71079b46ad5433165feaa2001450f2017b56
+Author: Przemysław Buczkowski <prem@prem.moe>
+Date:   Mon Aug 16 13:16:21 2021 +0100
+
+    GCC: Patch for Apple Silicon compatibility
+    
+    This patch fixes a linker error occuring when compiling
+    the cross-compiler on macOS and ARM64 architecture.
+    
+    Adapted from:
+    https://github.com/richfelker/musl-cross-make/issues/116#issuecomment-823612404
+    
+    Change-Id: Ia3ee98a163bbb62689f42e2da83a5ef36beb0913
+    Reviewed-on: https://review.haiku-os.org/c/buildtools/+/4329
+    Reviewed-by: John Scipione <jscipione@gmail.com>
+    Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
+
+--- a/gcc/config/aarch64/aarch64.h
++++ b/gcc/config/aarch64/aarch64.h
+@@ -1410,7 +1410,7 @@ extern enum aarch64_code_model aarch64_c
+ 
+ /* Extra specs when building a native AArch64-hosted compiler.
+    Option rewriting rules based on host system.  */
+-#if defined(__aarch64__)
++#if defined(__aarch64__) && ! defined(__APPLE__)
+ extern const char *host_detect_local_cpu (int argc, const char **argv);
+ #define HAVE_LOCAL_CPU_DETECT
+ # define EXTRA_SPEC_FUNCTIONS                                           \
+--- a/gcc/config/host-darwin.cc
++++ b/gcc/config/host-darwin.cc
+@@ -23,6 +23,8 @@
+ #include "options.h"
+ #include "diagnostic-core.h"
+ #include "config/host-darwin.h"
++#include "hosthooks.h"
++#include "hosthooks-def.h"
+ #include <errno.h>
+ 
+ /* For Darwin (macOS only) platforms, without ASLR (PIE) enabled on the
+@@ -181,3 +183,5 @@ darwin_gt_pch_use_address (void *&addr,
+ 
+   return 1;
+ }
++
++const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/toolchain/gdb/Makefile b/toolchain/gdb/Makefile
new file mode 100644
index 0000000..9b9ee5a
--- /dev/null
+++ b/toolchain/gdb/Makefile
@@ -0,0 +1,77 @@
+#
+# Copyright (C) 2006-2020 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=gdb
+PKG_VERSION:=15.2
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+PKG_SOURCE_URL:=@GNU/gdb
+PKG_HASH:=83350ccd35b5b5a0cba6b334c41294ea968158c573940904f00b92f76345314d
+PKG_CPE_ID:=cpe:/a:gnu:gdb
+GDB_DIR:=$(PKG_NAME)-$(PKG_VERSION)
+
+HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(GDB_DIR)
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+export ZSTD_CFLAGS=-I$(STAGING_DIR_HOST)/include -pthread
+export ZSTD_LIBS=-L$(STAGING_DIR_HOST)/lib -lzstd -lpthread
+
+HOST_CONFIGURE_VARS += \
+	acx_cv_cc_gcc_supports_ada=false \
+	gdb_cv_func_sigsetjmp=yes
+
+HOST_CONFIGURE_ARGS = \
+	--prefix=$(TOOLCHAIN_DIR) \
+	--build=$(GNU_HOST_NAME) \
+	--host=$(GNU_HOST_NAME) \
+	--target=$(REAL_GNU_TARGET_NAME) \
+	--with-gmp=$(STAGING_DIR_HOST) \
+	--with-mpfr=$(STAGING_DIR_HOST) \
+	--with-mpc=$(STAGING_DIR_HOST) \
+	--with-expat=$(STAGING_DIR_HOST) \
+	--disable-werror \
+	--without-uiout \
+	--enable-tui --disable-gdbtk --without-x \
+	--without-included-gettext \
+	--enable-threads \
+	--disable-unit-tests \
+	--disable-ubsan \
+	--disable-binutils \
+	--disable-ld \
+	--disable-gas \
+	--disable-sim
+
+ifneq ($(CONFIG_GDB_PYTHON),)
+  HOST_CONFIGURE_ARGS+= --with-python
+else
+  HOST_CONFIGURE_ARGS+= --without-python
+endif
+
+define Host/Install
+	mkdir -p $(TOOLCHAIN_DIR)/bin
+	$(INSTALL_BIN) $(HOST_BUILD_DIR)/gdb/gdb $(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)gdb
+	ln -fs $(TARGET_CROSS)gdb $(TOOLCHAIN_DIR)/bin/$(GNU_TARGET_NAME)-gdb
+	strip $(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)gdb
+	mkdir -p $(TOOLCHAIN_DIR)/share/gdb
+	-cp -R $(HOST_BUILD_DIR)/gdb/data-directory/python $(TOOLCHAIN_DIR)/share/gdb/
+	cp -R $(HOST_BUILD_DIR)/gdb/data-directory/syscalls $(TOOLCHAIN_DIR)/share/gdb/
+	cp -R $(HOST_BUILD_DIR)/gdb/data-directory/system-gdbinit $(TOOLCHAIN_DIR)/share/gdb/
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(TOOLCHAIN_DIR)/bin/$(TARGET_CROSS)gdb \
+		$(TOOLCHAIN_DIR)/bin/$(GNU_TARGET_NAME)-gdb
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/gdb/patches/120-fix-compile-flag-mismatch.patch b/toolchain/gdb/patches/120-fix-compile-flag-mismatch.patch
new file mode 100644
index 0000000..f9c5670
--- /dev/null
+++ b/toolchain/gdb/patches/120-fix-compile-flag-mismatch.patch
@@ -0,0 +1,11 @@
+--- a/gdbserver/configure
++++ b/gdbserver/configure
+@@ -2698,7 +2698,7 @@ $as_echo "$as_me: error: \`$ac_var' was
+       ac_cache_corrupted=: ;;
+     ,);;
+     *)
+-      if test "x$ac_old_val" != "x$ac_new_val"; then
++      if test "`echo x$ac_old_val`" != "`echo x$ac_new_val`"; then
+ 	# differences in whitespace do not lead to failure.
+ 	ac_old_val_w=`echo x $ac_old_val`
+ 	ac_new_val_w=`echo x $ac_new_val`
diff --git a/toolchain/glibc/Makefile b/toolchain/glibc/Makefile
new file mode 100644
index 0000000..bfb5598
--- /dev/null
+++ b/toolchain/glibc/Makefile
@@ -0,0 +1,32 @@
+PATH_PREFIX := .
+VARIANT:=final
+HOST_BUILD_PARALLEL:=1
+
+include ./common.mk
+
+define Host/Compile
+	+$(MAKE) -C $(CUR_BUILD_DIR) \
+		PARALLELMFLAGS="$(HOST_JOBS)" \
+		BUILD_CFLAGS="$(HOST_CFLAGS)" \
+		default-rpath="/lib:/usr/lib" \
+		all
+endef
+
+define Host/Install
+	$(call Host/SetToolchainInfo)
+	$(MAKE) -C $(CUR_BUILD_DIR) \
+		BUILD_CFLAGS="$(HOST_CFLAGS)" \
+		install_root="$(TOOLCHAIN_DIR)" \
+		install
+	( cd $(TOOLCHAIN_DIR) ; \
+		for d in lib usr/lib ; do \
+		  for f in libc.so libm.so libpthread.so libgcc_s.so ; do \
+		    if [ -f $$$$d/$$$$f -a ! -L $$$$d/$$$$f ] ; then \
+		      $(SED) 's,/usr/lib/,,g;s,/lib/,,g' $$$$d/$$$$f ; \
+		    fi \
+		  done \
+		done \
+	)
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/glibc/common.mk b/toolchain/glibc/common.mk
new file mode 100644
index 0000000..f4c0c66
--- /dev/null
+++ b/toolchain/glibc/common.mk
@@ -0,0 +1,104 @@
+#
+# Copyright (C) 2006-2020 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=glibc
+PKG_VERSION:=2.38
+PKG_RELEASE:=1
+
+PKG_SOURCE_PROTO:=git
+PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
+PKG_SOURCE_VERSION:=e9f05fa1c62c8044ff025963498063f73eb51c5f
+PKG_MIRROR_HASH:=fd61eb2caea0d4100638b8aa8285b0f1bc23af921c376516307c9ab8ac307739
+PKG_SOURCE_URL:=https://sourceware.org/git/glibc.git
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.zst
+PKG_CPE_ID:=cpe:/a:gnu:glibc
+
+HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(PKG_SOURCE_SUBDIR)
+CUR_BUILD_DIR:=$(HOST_BUILD_DIR)-$(VARIANT)
+PATCH_DIR:=$(PATH_PREFIX)/patches
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+HOST_STAMP_PREPARED:=$(HOST_BUILD_DIR)/.prepared
+HOST_STAMP_CONFIGURED:=$(CUR_BUILD_DIR)/.configured
+HOST_STAMP_BUILT:=$(CUR_BUILD_DIR)/.built
+HOST_STAMP_INSTALLED:=$(TOOLCHAIN_DIR)/stamp/.glibc_$(VARIANT)_installed
+
+ifeq ($(ARCH),mips64)
+  ifdef CONFIG_MIPS64_ABI_N64
+    TARGET_CFLAGS += -mabi=64
+  endif
+  ifdef CONFIG_MIPS64_ABI_N32
+    TARGET_CFLAGS += -mabi=n32
+  endif
+  ifdef CONFIG_MIPS64_ABI_O32
+    TARGET_CFLAGS += -mabi=32
+  endif
+endif
+
+TARGET_CFLAGS := $(filter-out -D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64,$(TARGET_CFLAGS))
+
+# -Os miscompiles w. 2.24 gcc5/gcc6
+# only -O2 tested by upstream changeset
+# "Optimize i386 syscall inlining for GCC 5"
+GLIBC_CONFIGURE:= \
+	unset LD_LIBRARY_PATH; \
+	BUILD_CC="$(HOSTCC)" \
+	$(TARGET_CONFIGURE_OPTS) \
+	CFLAGS="-O2 $(filter-out -Os,$(call qstrip,$(TARGET_CFLAGS)))" \
+	libc_cv_slibdir="/lib" \
+	use_ldconfig=no \
+	$(HOST_BUILD_DIR)/$(GLIBC_PATH)configure \
+		--prefix= \
+		--build=$(GNU_HOST_NAME) \
+		--host=$(REAL_GNU_TARGET_NAME) \
+		--with-headers=$(TOOLCHAIN_DIR)/include \
+		--disable-profile \
+		--disable-werror \
+		--without-gd \
+		--without-cvs \
+		--enable-add-ons \
+		--enable-crypt \
+		--$(if $(CONFIG_SOFT_FLOAT),without,with)-fp \
+		  $(if $(CONFIG_PKG_CC_STACKPROTECTOR_REGULAR),--enable-stack-protector=yes) \
+		  $(if $(CONFIG_PKG_CC_STACKPROTECTOR_STRONG),--enable-stack-protector=strong) \
+		  $(if $(CONFIG_PKG_CC_STACKPROTECTOR_ALL),--enable-stack-protector=all) \
+		  $(if $(CONFIG_PKG_RELRO_FULL),--enable-bind-now) \
+		  $(if $(CONFIG_PKG_FORTIFY_SOURCE_1),--enable-fortify-source=1) \
+		  $(if $(CONFIG_PKG_FORTIFY_SOURCE_2),--enable-fortify-source=2) \
+		--enable-kernel=4.14.0
+
+export libc_cv_ssp=no
+export libc_cv_ssp_strong=no
+export ac_cv_header_cpuid_h=yes
+export HOST_CFLAGS := $(HOST_CFLAGS) -idirafter $(CURDIR)/$(PATH_PREFIX)/include
+
+define Host/SetToolchainInfo
+	$(SED) 's,^\(LIBC_TYPE\)=.*,\1=$(PKG_NAME),' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_URL\)=.*,\1=http://www.gnu.org/software/libc/,' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_VERSION\)=.*,\1=$(PKG_VERSION),' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_SO_VERSION\)=.*,\1=$(PKG_VERSION),' $(TOOLCHAIN_DIR)/info.mk
+endef
+
+define Host/Configure
+	mkdir -p $(CUR_BUILD_DIR)
+	( cd $(CUR_BUILD_DIR); rm -f config.cache; \
+		$(GLIBC_CONFIGURE) \
+	);
+endef
+
+define Host/Prepare
+	$(call Host/Prepare/Default)
+	ln -snf $(PKG_SOURCE_SUBDIR) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+endef
+
+define Host/Clean
+	rm -rf $(CUR_BUILD_DIR)* \
+		$(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev \
+		$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+endef
diff --git a/toolchain/glibc/headers/Makefile b/toolchain/glibc/headers/Makefile
new file mode 100644
index 0000000..f1d8a8b
--- /dev/null
+++ b/toolchain/glibc/headers/Makefile
@@ -0,0 +1,28 @@
+PATH_PREFIX:=..
+VARIANT:=headers
+
+include ../common.mk
+
+define Host/Compile
+
+endef
+
+define Host/Install
+	$(call Host/SetToolchainInfo)
+	mkdir -p $(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev/{include,lib}
+	$(MAKE) -C $(CUR_BUILD_DIR) \
+		BUILD_CFLAGS="$(HOST_CFLAGS)" \
+		install_root="$(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev" \
+		install-bootstrap-headers=yes \
+		install-headers
+	$(CP) $(BUILD_DIR_TOOLCHAIN)/linux-dev/* $(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev/
+	$(MAKE) -C $(CUR_BUILD_DIR) \
+		csu/subdir_lib
+	( cd $(CUR_BUILD_DIR); \
+		$(CP) csu/crt1.o csu/crti.o csu/crtn.o $(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev/lib/ \
+	)
+	$(TARGET_CC) -nostdlib -nostartfiles -shared -x c /dev/null \
+		-o $(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev/lib/libc.so
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/glibc/include/libintl.h b/toolchain/glibc/include/libintl.h
new file mode 100644
index 0000000..69cb887
--- /dev/null
+++ b/toolchain/glibc/include/libintl.h
@@ -0,0 +1,6 @@
+#ifndef __FAKE_LIBINTL_H
+#define __FAKE_LIBINTL_H
+
+#define _(X) (X)
+
+#endif
diff --git a/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch b/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch
new file mode 100644
index 0000000..771cb4c
--- /dev/null
+++ b/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch
@@ -0,0 +1,677 @@
+From 08f5e0df46ce1ad617bcde1fd5542545397630b9 Mon Sep 17 00:00:00 2001
+From: Hans Dedecker <dedeckeh@gmail.com>
+Date: Sat, 24 Oct 2020 21:13:30 +0200
+Subject: Revert "Disallow use of DES encryption functions in new programs."
+
+This reverts commit b10a0accee709a5efff2fadf0b0bbb79ff0ad759.
+
+ppp still uses the encrypt functions from the libc while musl libc also
+provides them.
+---
+ conform/data/stdlib.h-data |   3 +
+ conform/data/unistd.h-data |   6 ++
+ crypt/cert.c               |  26 -----
+ crypt/crypt-entry.c        |  15 ++-
+ crypt/crypt.h              |  16 +++
+ crypt/crypt_util.c         |   9 --
+ manual/conf.texi           |   2 -
+ manual/crypt.texi          | 204 +++++++++++++++++++++++++++++++++++++
+ manual/string.texi         |  82 +++++++--------
+ posix/unistd.h             |  17 +++-
+ stdlib/stdlib.h            |   6 ++
+ sunrpc/des_crypt.c         |   7 +-
+ sunrpc/des_soft.c          |   2 +-
+ 13 files changed, 305 insertions(+), 90 deletions(-)
+
+--- a/conform/data/stdlib.h-data
++++ b/conform/data/stdlib.h-data
+@@ -149,6 +149,9 @@ function {unsigned short int*} seed48 (u
+ #if !defined ISO && !defined ISO99 && !defined ISO11 && !defined POSIX && !defined XPG4 && !defined XPG42 && !defined UNIX98
+ function int setenv (const char*, const char*, int)
+ #endif
++#if !defined ISO && !defined ISO99 && !defined ISO11 && !defined POSIX && !defined POSIX2008
++function void setkey (const char*)
++#endif
+ #if !defined ISO && !defined ISO99 && !defined ISO11 && !defined XPG4 && !defined POSIX && !defined POSIX2008
+ function {char*} setstate (char*)
+ #endif
+--- a/conform/data/unistd.h-data
++++ b/conform/data/unistd.h-data
+@@ -437,6 +437,9 @@ function int chroot (const char*)
+ function int chown (const char*, uid_t, gid_t)
+ function int close (int)
+ function size_t confstr (int, char*, size_t)
++#if !defined POSIX && !defined POSIX2008
++function {char*} crypt (const char*, const char*)
++#endif
+ #if defined XPG4 || defined XPG42 || defined UNIX98
+ function {char*} ctermid (char*)
+ function {char*} cuserid (char*)
+@@ -446,6 +449,9 @@ allow cuserid
+ #endif
+ function int dup (int)
+ function int dup2 (int, int)
++#if !defined POSIX && !defined POSIX2008
++function void encrypt (char[64], int)
++#endif
+ function int execl (const char*, const char*, ...)
+ function int execle (const char*, const char*, ...)
+ function int execlp (const char*, const char*, ...)
+--- a/crypt/cert.c
++++ b/crypt/cert.c
+@@ -10,22 +10,6 @@
+ #include <stdlib.h>
+ #include "crypt.h"
+ 
+-/* This file tests the deprecated setkey/encrypt interface.  */
+-#include <shlib-compat.h>
+-#if TEST_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
+-
+-#define libcrypt_version_reference(symbol, version) \
+-  _libcrypt_version_reference (symbol, VERSION_libcrypt_##version)
+-#define _libcrypt_version_reference(symbol, version) \
+-  __libcrypt_version_reference (symbol, version)
+-#define __libcrypt_version_reference(symbol, version) \
+-  __asm__ (".symver " #symbol ", " #symbol "@" #version)
+-
+-extern void setkey (const char *);
+-extern void encrypt (const char *, int);
+-libcrypt_version_reference (setkey, GLIBC_2_0);
+-libcrypt_version_reference (encrypt, GLIBC_2_0);
+-
+ int totfails = 0;
+ 
+ int main (int argc, char *argv[]);
+@@ -123,13 +107,3 @@ put8 (char *cp)
+ 	  printf("%02x", t);
+ 	}
+ }
+-
+-#else /* encrypt and setkey are not available.  */
+-
+-int
+-main (void)
+-{
+-  return 77; /* UNSUPPORTED */
+-}
+-
+-#endif
+--- a/crypt/crypt-entry.c
++++ b/crypt/crypt-entry.c
+@@ -35,7 +35,6 @@
+ #endif
+ 
+ #include "crypt-private.h"
+-#include <shlib-compat.h>
+ 
+ /* Prototypes for local functions.  */
+ #ifndef __GNU_LIBRARY__
+@@ -177,7 +176,17 @@ crypt (const char *key, const char *salt
+   return __crypt_r (key, salt, &_ufc_foobar);
+ }
+ 
+-#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
++
++/*
++ * To make fcrypt users happy.
++ * They don't need to call init_des.
++ */
++#ifdef _LIBC
+ weak_alias (crypt, fcrypt)
+-compat_symbol (libcrypt, fcrypt, fcrypt, GLIBC_2_0);
++#else
++char *
++__fcrypt (const char *key, const char *salt)
++{
++  return crypt (key, salt);
++}
+ #endif
+--- a/crypt/crypt.h
++++ b/crypt/crypt.h
+@@ -36,6 +36,14 @@ __BEGIN_DECLS
+ extern char *crypt (const char *__phrase, const char *__salt)
+      __THROW __nonnull ((1, 2));
+ 
++/* Setup DES tables according KEY.  */
++extern void setkey (const char *__key) __THROW __nonnull ((1));
++
++/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
++   block in place.  */
++extern void encrypt (char *__glibc_block, int __edflag)
++     __THROW __nonnull ((1));
++
+ #ifdef __USE_GNU
+ 
+ /* This structure provides scratch and output buffers for 'crypt_r'.
+@@ -63,6 +71,14 @@ struct crypt_data
+ extern char *crypt_r (const char *__phrase, const char *__salt,
+ 		      struct crypt_data * __restrict __data)
+      __THROW __nonnull ((1, 2, 3));
++
++extern void setkey_r (const char *__key,
++		      struct crypt_data * __restrict __data)
++     __THROW __nonnull ((1, 2));
++
++extern void encrypt_r (char *__glibc_block, int __edflag,
++		       struct crypt_data * __restrict __data)
++     __THROW __nonnull ((1, 3));
+ #endif
+ 
+ __END_DECLS
+--- a/crypt/crypt_util.c
++++ b/crypt/crypt_util.c
+@@ -34,7 +34,6 @@
+ #endif
+ 
+ #include "crypt-private.h"
+-#include <shlib-compat.h>
+ 
+ /* Prototypes for local functions.  */
+ #ifndef __GNU_LIBRARY__
+@@ -151,7 +150,6 @@ static const int sbox[8][4][16]= {
+ 	}
+ };
+ 
+-#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
+ /*
+  * This is the initial
+  * permutation matrix
+@@ -162,7 +160,6 @@ static const int initial_perm[64] = {
+   57, 49, 41, 33, 25, 17,  9,  1, 59, 51, 43, 35, 27, 19, 11, 3,
+   61, 53, 45, 37, 29, 21, 13,  5, 63, 55, 47, 39, 31, 23, 15, 7
+ };
+-#endif
+ 
+ /*
+  * This is the final
+@@ -788,7 +785,6 @@ _ufc_output_conversion_r (ufc_long v1, u
+   __data->crypt_3_buf[13] = 0;
+ }
+ 
+-#if SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28)
+ 
+ /*
+  * UNIX encrypt function. Takes a bitvector
+@@ -889,14 +885,12 @@ __encrypt_r (char *__block, int __edflag
+   }
+ }
+ weak_alias (__encrypt_r, encrypt_r)
+-compat_symbol (libcrypt, encrypt_r, encrypt_r, GLIBC_2_0);
+ 
+ void
+ encrypt (char *__block, int __edflag)
+ {
+   __encrypt_r(__block, __edflag, &_ufc_foobar);
+ }
+-compat_symbol (libcrypt, encrypt, encrypt, GLIBC_2_0);
+ 
+ 
+ /*
+@@ -921,15 +915,12 @@ __setkey_r (const char *__key, struct cr
+   _ufc_mk_keytab_r((char *) ktab, __data);
+ }
+ weak_alias (__setkey_r, setkey_r)
+-compat_symbol (libcrypt, setkey_r, setkey_r, GLIBC_2_0);
+ 
+ void
+ setkey (const char *__key)
+ {
+   __setkey_r(__key, &_ufc_foobar);
+ }
+-compat_symbol (libcrypt, setkey, setkey, GLIBC_2_0);
+-#endif /* SHLIB_COMPAT (libcrypt, GLIBC_2_0, GLIBC_2_28) */
+ 
+ void
+ __b64_from_24bit (char **cp, int *buflen,
+--- a/manual/conf.texi
++++ b/manual/conf.texi
+@@ -780,8 +780,6 @@ Inquire about the parameter correspondin
+ @item _SC_XOPEN_CRYPT
+ @standards{X/Open, unistd.h}
+ Inquire about the parameter corresponding to @code{_XOPEN_CRYPT}.
+-@Theglibc no longer implements the @code{_XOPEN_CRYPT} extensions,
+-so @samp{sysconf (_SC_XOPEN_CRYPT)} always returns @code{-1}.
+ 
+ @item _SC_XOPEN_ENH_I18N
+ @standards{X/Open, unistd.h}
+--- a/manual/crypt.texi
++++ b/manual/crypt.texi
+@@ -16,8 +16,19 @@ subject to them, even if you do not use
+ yourself.  The restrictions vary from place to place and are changed
+ often, so we cannot give any more specific advice than this warning.
+ 
++@vindex AUTH_DES
++@cindex FIPS 140-2
++It also provides support for Secure RPC, and some library functions that
++can be used to perform normal DES encryption.  The @code{AUTH_DES}
++authentication flavor in Secure RPC, as provided by @theglibc{},
++uses DES and does not comply with FIPS 140-2 nor does any other use of DES
++within @theglibc{}.  It is recommended that Secure RPC should not be used
++for systems that need to comply with FIPS 140-2 since all flavors of
++encrypted authentication use normal DES.
++
+ @menu
+ * Passphrase Storage::          One-way hashing for passphrases.
++* crypt::                       A one-way function for passwords.
+ * Unpredictable Bytes::         Randomness for cryptographic purposes.
+ @end menu
+ 
+@@ -190,6 +201,199 @@ unpredictable as possible; @pxref{Unpred
+ @include genpass.c.texi
+ @end smallexample
+ 
++@node DES Encryption
++@section DES Encryption
++
++@cindex FIPS 46-3
++The Data Encryption Standard is described in the US Government Federal
++Information Processing Standards (FIPS) 46-3 published by the National
++Institute of Standards and Technology.  The DES has been very thoroughly
++analyzed since it was developed in the late 1970s, and no new
++significant flaws have been found.
++
++However, the DES uses only a 56-bit key (plus 8 parity bits), and a
++machine has been built in 1998 which can search through all possible
++keys in about 6 days, which cost about US$200000; faster searches would
++be possible with more money.  This makes simple DES insecure for most
++purposes, and NIST no longer permits new US government systems
++to use simple DES.
++
++For serious encryption functionality, it is recommended that one of the
++many free encryption libraries be used instead of these routines.
++
++The DES is a reversible operation which takes a 64-bit block and a
++64-bit key, and produces another 64-bit block.  Usually the bits are
++numbered so that the most-significant bit, the first bit, of each block
++is numbered 1.
++
++Under that numbering, every 8th bit of the key (the 8th, 16th, and so
++on) is not used by the encryption algorithm itself.  But the key must
++have odd parity; that is, out of bits 1 through 8, and 9 through 16, and
++so on, there must be an odd number of `1' bits, and this completely
++specifies the unused bits.
++
++@deftypefun void setkey (const char *@var{key})
++@standards{BSD, crypt.h}
++@standards{SVID, crypt.h}
++@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
++@c The static buffer stores the key, making it fundamentally
++@c thread-unsafe.  The locking issues are only in the initialization
++@c path; cancelling the initialization will leave the lock held, it
++@c would otherwise repeat the initialization on the next call.
++
++The @code{setkey} function sets an internal data structure to be an
++expanded form of @var{key}.  @var{key} is specified as an array of 64
++bits each stored in a @code{char}, the first bit is @code{key[0]} and
++the 64th bit is @code{key[63]}.  The @var{key} should have the correct
++parity.
++@end deftypefun
++
++@deftypefun void encrypt (char *@var{block}, int @var{edflag})
++@standards{BSD, crypt.h}
++@standards{SVID, crypt.h}
++@safety{@prelim{}@mtunsafe{@mtasurace{:crypt}}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
++@c Same issues as setkey.
++
++The @code{encrypt} function encrypts @var{block} if
++@var{edflag} is 0, otherwise it decrypts @var{block}, using a key
++previously set by @code{setkey}.  The result is
++placed in @var{block}.
++
++Like @code{setkey}, @var{block} is specified as an array of 64 bits each
++stored in a @code{char}, but there are no parity bits in @var{block}.
++@end deftypefun
++
++@deftypefun void setkey_r (const char *@var{key}, {struct crypt_data *} @var{data})
++@deftypefunx void encrypt_r (char *@var{block}, int @var{edflag}, {struct crypt_data *} @var{data})
++@standards{GNU, crypt.h}
++@c setkey_r: @safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
++@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{} @asulock{}}@acunsafe{@aculock{}}}
++
++These are reentrant versions of @code{setkey} and @code{encrypt}.  The
++only difference is the extra parameter, which stores the expanded
++version of @var{key}.  Before calling @code{setkey_r} the first time,
++@code{data->initialized} must be cleared to zero.
++@end deftypefun
++
++The @code{setkey_r} and @code{encrypt_r} functions are GNU extensions.
++@code{setkey}, @code{encrypt}, @code{setkey_r}, and @code{encrypt_r} are
++defined in @file{crypt.h}.
++
++@deftypefun int ecb_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode})
++@standards{SUNRPC, rpc/des_crypt.h}
++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
++
++The function @code{ecb_crypt} encrypts or decrypts one or more blocks
++using DES.  Each block is encrypted independently.
++
++The @var{blocks} and the @var{key} are stored packed in 8-bit bytes, so
++that the first bit of the key is the most-significant bit of
++@code{key[0]} and the 63rd bit of the key is stored as the
++least-significant bit of @code{key[7]}.  The @var{key} should have the
++correct parity.
++
++@var{len} is the number of bytes in @var{blocks}.  It should be a
++multiple of 8 (so that there are a whole number of blocks to encrypt).
++@var{len} is limited to a maximum of @code{DES_MAXDATA} bytes.
++
++The result of the encryption replaces the input in @var{blocks}.
++
++The @var{mode} parameter is the bitwise OR of two of the following:
++
++@vtable @code
++@item DES_ENCRYPT
++@standards{SUNRPC, rpc/des_crypt.h}
++This constant, used in the @var{mode} parameter, specifies that
++@var{blocks} is to be encrypted.
++
++@item DES_DECRYPT
++@standards{SUNRPC, rpc/des_crypt.h}
++This constant, used in the @var{mode} parameter, specifies that
++@var{blocks} is to be decrypted.
++
++@item DES_HW
++@standards{SUNRPC, rpc/des_crypt.h}
++This constant, used in the @var{mode} parameter, asks to use a hardware
++device.  If no hardware device is available, encryption happens anyway,
++but in software.
++
++@item DES_SW
++@standards{SUNRPC, rpc/des_crypt.h}
++This constant, used in the @var{mode} parameter, specifies that no
++hardware device is to be used.
++@end vtable
++
++The result of the function will be one of these values:
++
++@vtable @code
++@item DESERR_NONE
++@standards{SUNRPC, rpc/des_crypt.h}
++The encryption succeeded.
++
++@item DESERR_NOHWDEVICE
++@standards{SUNRPC, rpc/des_crypt.h}
++The encryption succeeded, but there was no hardware device available.
++
++@item DESERR_HWERROR
++@standards{SUNRPC, rpc/des_crypt.h}
++The encryption failed because of a hardware problem.
++
++@item DESERR_BADPARAM
++@standards{SUNRPC, rpc/des_crypt.h}
++The encryption failed because of a bad parameter, for instance @var{len}
++is not a multiple of 8 or @var{len} is larger than @code{DES_MAXDATA}.
++@end vtable
++@end deftypefun
++
++@deftypefun int DES_FAILED (int @var{err})
++@standards{SUNRPC, rpc/des_crypt.h}
++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
++This macro returns 1 if @var{err} is a `success' result code from
++@code{ecb_crypt} or @code{cbc_crypt}, and 0 otherwise.
++@end deftypefun
++
++@deftypefun int cbc_crypt (char *@var{key}, char *@var{blocks}, unsigned int @var{len}, unsigned int @var{mode}, char *@var{ivec})
++@standards{SUNRPC, rpc/des_crypt.h}
++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
++
++The function @code{cbc_crypt} encrypts or decrypts one or more blocks
++using DES in Cipher Block Chaining mode.
++
++For encryption in CBC mode, each block is exclusive-ored with @var{ivec}
++before being encrypted, then @var{ivec} is replaced with the result of
++the encryption, then the next block is processed.  Decryption is the
++reverse of this process.
++
++This has the advantage that blocks which are the same before being
++encrypted are very unlikely to be the same after being encrypted, making
++it much harder to detect patterns in the data.
++
++Usually, @var{ivec} is set to 8 random bytes before encryption starts.
++Then the 8 random bytes are transmitted along with the encrypted data
++(without themselves being encrypted), and passed back in as @var{ivec}
++for decryption.  Another possibility is to set @var{ivec} to 8 zeroes
++initially, and have the first block encrypted consist of 8 random
++bytes.
++
++Otherwise, all the parameters are similar to those for @code{ecb_crypt}.
++@end deftypefun
++
++@deftypefun void des_setparity (char *@var{key})
++@standards{SUNRPC, rpc/des_crypt.h}
++@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
++
++The function @code{des_setparity} changes the 64-bit @var{key}, stored
++packed in 8-bit bytes, to have odd parity by altering the low bits of
++each byte.
++@end deftypefun
++
++The @code{ecb_crypt}, @code{cbc_crypt}, and @code{des_setparity}
++functions and their accompanying macros are all defined in the header
++@file{rpc/des_crypt.h}.
++
++@node Unpredictable Bytes
++@section Generating Unpredictable Bytes
++
+ The next program demonstrates how to verify a passphrase.  It checks a
+ hash hardcoded into the program, because looking up real users' hashed
+ passphrases may require special privileges (@pxref{User Database}).
+--- a/manual/string.texi
++++ b/manual/string.texi
+@@ -36,8 +36,8 @@ too.
+ 				 for delimiters.
+ * Erasing Sensitive Data::      Clearing memory which contains sensitive
+                                  data, after it's no longer needed.
+-* Shuffling Bytes::             Or how to flash-cook a string.
+-* Obfuscating Data::            Reversibly obscuring data from casual view.
++* strfry::                      Function for flash-cooking a string.
++* Trivial Encryption::          Obscuring data.
+ * Encode Binary Data::          Encoding and Decoding of Binary Data.
+ * Argz and Envz Vectors::       Null-separated string vectors.
+ @end menu
+@@ -2512,73 +2512,73 @@ functionality under a different name, su
+ systems it may be in @file{strings.h} instead.
+ @end deftypefun
+ 
+-
+-@node Shuffling Bytes
+-@section Shuffling Bytes
++@node strfry
++@section strfry
+ 
+ The function below addresses the perennial programming quandary: ``How do
+ I take good data in string form and painlessly turn it into garbage?''
+-This is not a difficult thing to code for oneself, but the authors of
+-@theglibc{} wish to make it as convenient as possible.
++This is actually a fairly simple task for C programmers who do not use
++@theglibc{} string functions, but for programs based on @theglibc{},
++the @code{strfry} function is the preferred method for
++destroying string data.
+ 
+-To @emph{erase} data, use @code{explicit_bzero} (@pxref{Erasing
+-Sensitive Data}); to obfuscate it reversibly, use @code{memfrob}
+-(@pxref{Obfuscating Data}).
++The prototype for this function is in @file{string.h}.
+ 
+ @deftypefun {char *} strfry (char *@var{string})
+ @standards{GNU, string.h}
+ @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+ @c Calls initstate_r, time, getpid, strlen, and random_r.
+ 
+-@code{strfry} performs an in-place shuffle on @var{string}.  Each
+-character is swapped to a position selected at random, within the
+-portion of the string starting with the character's original position.
+-(This is the Fisher-Yates algorithm for unbiased shuffling.)
+-
+-Calling @code{strfry} will not disturb any of the random number
+-generators that have global state (@pxref{Pseudo-Random Numbers}).
++@code{strfry} creates a pseudorandom anagram of a string, replacing the
++input with the anagram in place.  For each position in the string,
++@code{strfry} swaps it with a position in the string selected at random
++(from a uniform distribution).  The two positions may be the same.
+ 
+ The return value of @code{strfry} is always @var{string}.
+ 
+ @strong{Portability Note:}  This function is unique to @theglibc{}.
+-It is declared in @file{string.h}.
++
+ @end deftypefun
+ 
+ 
+-@node Obfuscating Data
+-@section Obfuscating Data
++@node Trivial Encryption
++@section Trivial Encryption
++@cindex encryption
++
++
++The @code{memfrob} function converts an array of data to something
++unrecognizable and back again.  It is not encryption in its usual sense
++since it is easy for someone to convert the encrypted data back to clear
++text.  The transformation is analogous to Usenet's ``Rot13'' encryption
++method for obscuring offensive jokes from sensitive eyes and such.
++Unlike Rot13, @code{memfrob} works on arbitrary binary data, not just
++text.
+ @cindex Rot13
+ 
+-The @code{memfrob} function reversibly obfuscates an array of binary
+-data.  This is not true encryption; the obfuscated data still bears a
+-clear relationship to the original, and no secret key is required to
+-undo the obfuscation.  It is analogous to the ``Rot13'' cipher used on
+-Usenet for obscuring offensive jokes, spoilers for works of fiction,
+-and so on, but it can be applied to arbitrary binary data.
+-
+-Programs that need true encryption---a transformation that completely
+-obscures the original and cannot be reversed without knowledge of a
+-secret key---should use a dedicated cryptography library, such as
+-@uref{https://www.gnu.org/software/libgcrypt/,,libgcrypt}.
+-
+-Programs that need to @emph{destroy} data should use
+-@code{explicit_bzero} (@pxref{Erasing Sensitive Data}), or possibly
+-@code{strfry} (@pxref{Shuffling Bytes}).
++For true encryption, @xref{Cryptographic Functions}.
++
++This function is declared in @file{string.h}.
++@pindex string.h
+ 
+ @deftypefun {void *} memfrob (void *@var{mem}, size_t @var{length})
+ @standards{GNU, string.h}
+ @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+ 
+-The function @code{memfrob} obfuscates @var{length} bytes of data
+-beginning at @var{mem}, in place.  Each byte is bitwise xor-ed with
+-the binary pattern 00101010 (hexadecimal 0x2A).  The return value is
+-always @var{mem}.
+-
+-@code{memfrob} a second time on the same data returns it to
+-its original state.
++@code{memfrob} transforms (frobnicates) each byte of the data structure
++at @var{mem}, which is @var{length} bytes long, by bitwise exclusive
++oring it with binary 00101010.  It does the transformation in place and
++its return value is always @var{mem}.
++
++Note that @code{memfrob} a second time on the same data structure
++returns it to its original state.
++
++This is a good function for hiding information from someone who doesn't
++want to see it or doesn't want to see it very much.  To really prevent
++people from retrieving the information, use stronger encryption such as
++that described in @xref{Cryptographic Functions}.
+ 
+ @strong{Portability Note:}  This function is unique to @theglibc{}.
+-It is declared in @file{string.h}.
++
+ @end deftypefun
+ 
+ @node Encode Binary Data
+--- a/posix/unistd.h
++++ b/posix/unistd.h
+@@ -107,6 +107,9 @@ __BEGIN_DECLS
+ /* The X/Open Unix extensions are available.  */
+ #define _XOPEN_UNIX	1
+ 
++/* Encryption is present.  */
++#define	_XOPEN_CRYPT	1
++
+ /* The enhanced internationalization capabilities according to XPG4.2
+    are present.  */
+ #define	_XOPEN_ENH_I18N	1
+@@ -1150,17 +1153,25 @@ ssize_t copy_file_range (int __infd, __o
+ extern int fdatasync (int __fildes);
+ #endif /* Use POSIX199309 */
+ 
+-#ifdef __USE_MISC
++/* XPG4.2 specifies that prototypes for the encryption functions must
++   be defined here.  */
++#ifdef	__USE_XOPEN
+ /* One-way hash PHRASE, returning a string suitable for storage in the
+    user database.  SALT selects the one-way function to use, and
+    ensures that no two users' hashes are the same, even if they use
+    the same passphrase.  The return value points to static storage
+    which will be overwritten by the next call to crypt.  */
++
++/* Encrypt at most 8 characters from KEY using salt to perturb DES.  */
+ extern char *crypt (const char *__key, const char *__salt)
+      __THROW __nonnull ((1, 2));
+-#endif
+ 
+-#ifdef	__USE_XOPEN
++/* Encrypt data in BLOCK in place if EDFLAG is zero; otherwise decrypt
++   block in place.  */
++extern void encrypt (char *__glibc_block, int __edflag)
++     __THROW __nonnull ((1));
++
++
+ /* Swab pairs bytes in the first N bytes of the area pointed to by
+    FROM and copy the result to TO.  The value of TO must not be in the
+    range [FROM - N + 1, FROM - 1].  If N is odd the first byte in FROM
+--- a/stdlib/stdlib.h
++++ b/stdlib/stdlib.h
+@@ -1103,6 +1103,12 @@ extern int getsubopt (char **__restrict
+ #endif
+ 
+ 
++#ifdef __USE_XOPEN
++/* Setup DES tables according KEY.  */
++extern void setkey (const char *__key) __THROW __nonnull ((1));
++#endif
++
++
+ /* X/Open pseudo terminal handling.  */
+ 
+ #ifdef __USE_XOPEN2KXSI
+--- a/sunrpc/des_crypt.c
++++ b/sunrpc/des_crypt.c
+@@ -86,9 +86,6 @@ common_crypt (char *key, char *buf, regi
+   return desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE;
+ }
+ 
+-/* Note: these cannot be excluded from the build yet, because they are
+-   still used internally.  */
+-
+ /*
+  * CBC mode encryption
+  */
+@@ -105,7 +102,7 @@ cbc_crypt (char *key, char *buf, unsigne
+   COPY8 (dp.des_ivec, ivec);
+   return err;
+ }
+-hidden_nolink (cbc_crypt, libc, GLIBC_2_1)
++libc_hidden_nolink_sunrpc (cbc_crypt, GLIBC_2_1)
+ 
+ /*
+  * ECB mode encryption
+@@ -118,4 +115,4 @@ ecb_crypt (char *key, char *buf, unsigne
+   dp.des_mode = ECB;
+   return common_crypt (key, buf, len, mode, &dp);
+ }
+-hidden_nolink (ecb_crypt, libc, GLIBC_2_1)
++libc_hidden_nolink_sunrpc (ecb_crypt, GLIBC_2_1)
+--- a/sunrpc/des_soft.c
++++ b/sunrpc/des_soft.c
+@@ -71,4 +71,4 @@ des_setparity (char *p)
+       p++;
+     }
+ }
+-hidden_nolink (des_setparity, libc, GLIBC_2_1)
++libc_hidden_nolink_sunrpc (des_setparity, GLIBC_2_1)
diff --git a/toolchain/glibc/patches/100-fix_cross_rpcgen.patch b/toolchain/glibc/patches/100-fix_cross_rpcgen.patch
new file mode 100644
index 0000000..9baed08
--- /dev/null
+++ b/toolchain/glibc/patches/100-fix_cross_rpcgen.patch
@@ -0,0 +1,36 @@
+--- a/sunrpc/rpc/types.h
++++ b/sunrpc/rpc/types.h
+@@ -75,18 +75,23 @@ typedef unsigned long rpcport_t;
+ #endif
+ 
+ #ifndef __u_char_defined
+-typedef __u_char u_char;
+-typedef __u_short u_short;
+-typedef __u_int u_int;
+-typedef __u_long u_long;
+-typedef __quad_t quad_t;
+-typedef __u_quad_t u_quad_t;
+-typedef __fsid_t fsid_t;
++typedef unsigned char u_char;
++typedef unsigned short u_short;
++typedef unsigned int u_int;
++typedef unsigned long u_long;
++#if __WORDSIZE == 64
++typedef long int quad_t;
++typedef unsigned long int u_quad_t;
++#elif defined __GLIBC_HAVE_LONG_LONG
++typedef long long int quad_t;
++typedef unsigned long long int u_quad_t;
++#endif
++typedef u_quad_t fsid_t;
+ # define __u_char_defined
+ #endif
+-#ifndef __daddr_t_defined
+-typedef __daddr_t daddr_t;
+-typedef __caddr_t caddr_t;
++#if !defined(__daddr_t_defined) && defined(linux)
++typedef long int daddr_t;
++typedef char *caddr_t;
+ # define __daddr_t_defined
+ #endif
+ 
diff --git a/toolchain/glibc/patches/200-add-dl-search-paths.patch b/toolchain/glibc/patches/200-add-dl-search-paths.patch
new file mode 100644
index 0000000..1510654
--- /dev/null
+++ b/toolchain/glibc/patches/200-add-dl-search-paths.patch
@@ -0,0 +1,14 @@
+add /usr/lib to default search path for the dynamic linker
+
+--- a/Makeconfig
++++ b/Makeconfig
+@@ -632,6 +632,9 @@ else
+ default-rpath = $(libdir)
+ endif
+ 
++# Add /usr/lib to default search path for the dynamic linker
++user-defined-trusted-dirs := /usr/lib
++
+ ifndef link-extra-libs
+ link-extra-libs = $(LDLIBS-$(@F))
+ link-extra-libs-static = $(link-extra-libs)
diff --git a/toolchain/glibc/patches/500-fix-building-arm-thumb.patch b/toolchain/glibc/patches/500-fix-building-arm-thumb.patch
new file mode 100644
index 0000000..05d56f0
--- /dev/null
+++ b/toolchain/glibc/patches/500-fix-building-arm-thumb.patch
@@ -0,0 +1,11 @@
+--- a/configure
++++ b/configure
+@@ -6882,7 +6882,7 @@ fi
+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_as_noexecstack" >&5
+ printf "%s\n" "$libc_cv_as_noexecstack" >&6; }
+ if test $libc_cv_as_noexecstack = yes; then
+-  ASFLAGS_config="$ASFLAGS_config -Wa,--noexecstack"
++  ASFLAGS_config="$ASFLAGS_config -Wa,--noexecstack $CFLAGS"
+ fi
+ 
+ 
diff --git a/toolchain/info.mk b/toolchain/info.mk
new file mode 100644
index 0000000..4f311c5
--- /dev/null
+++ b/toolchain/info.mk
@@ -0,0 +1,6 @@
+TARGET_CROSS=
+GCC_VERSION=unknown
+LIBC_TYPE=unknown
+LIBC_URL=unknown
+LIBC_VERSION=unknown
+LIBC_SO_VERSION=unknown
diff --git a/toolchain/kernel-headers/Makefile b/toolchain/kernel-headers/Makefile
new file mode 100644
index 0000000..dc70f32
--- /dev/null
+++ b/toolchain/kernel-headers/Makefile
@@ -0,0 +1,116 @@
+# 
+# Copyright (C) 2006-2009 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+KERNEL_BUILD_DIR := $(BUILD_DIR_TOOLCHAIN)
+BUILD_DIR := $(KERNEL_BUILD_DIR)
+
+override QUILT:=
+override HOST_QUILT:=
+
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=linux
+PKG_VERSION:=$(LINUX_VERSION)
+PKG_SOURCE:=$(LINUX_SOURCE)
+PKG_CPE_ID:=cpe:/o:linux:linux_kernel
+ifneq ($(call qstrip,$(CONFIG_KERNEL_GIT_CLONE_URI)),)
+  PKG_SOURCE_PROTO:=git
+  PKG_SOURCE_URL:=$(call qstrip,$(CONFIG_KERNEL_GIT_CLONE_URI))
+  PKG_SOURCE_VERSION:=$(call qstrip,$(CONFIG_KERNEL_GIT_REF))
+  PKG_MIRROR_HASH:=$(call qstrip,$(CONFIG_KERNEL_GIT_MIRROR_HASH))
+ifdef CHECK
+  PLATFORM_DIR:=$(firstword $(wildcard $(TOPDIR)/target/linux/feeds/$(BOARD) $(TOPDIR)/target/linux/$(BOARD)))
+  include $(PLATFORM_DIR)/Makefile
+  include $(INCLUDE_DIR)/kernel-version.mk
+  include $(INCLUDE_DIR)/kernel-build.mk
+  PKG_VERSION:=$(LINUX_VERSION)
+else
+  PKG_SOURCE:=$(LINUX_SOURCE)
+endif
+else
+  PKG_SOURCE:=$(LINUX_SOURCE)
+  PKG_SOURCE_URL:=$(LINUX_SITE)
+endif
+HOST_BUILD_DIR:=$(KERNEL_BUILD_DIR)/linux-$(LINUX_VERSION)
+PKG_HASH:=$(LINUX_KERNEL_HASH)
+LINUX_DIR := $(HOST_BUILD_DIR)
+FILES_DIR := 
+PATCH_DIR := ./patches$(if $(wildcard ./patches-$(LINUX_VERSION)),-$(LINUX_VERSION))
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+include $(INCLUDE_DIR)/kernel-defaults.mk
+
+ifeq ($(strip $(BOARD)),uml)
+  LINUX_KARCH:=$(subst x86_64,x86,$(subst i386,x86,$(ARCH)))
+endif
+
+HOST_EXTRACFLAGS=
+
+LINUX_HAS_HEADERS_INSTALL:=y
+
+HOST_KMAKE := $(MAKE) -C $(HOST_BUILD_DIR) \
+	$(KERNEL_MAKE_FLAGS) \
+	CC="$(KERNEL_CC)" \
+	HOSTCFLAGS="$(HOST_CFLAGS)"
+
+define Host/Configure/all
+	mkdir -p $(BUILD_DIR_TOOLCHAIN)/linux-dev
+	$(HOST_KMAKE) \
+		INSTALL_HDR_PATH="$(BUILD_DIR_TOOLCHAIN)/linux-dev/" \
+		headers_install
+endef
+
+# XXX: the following is needed to build lzma-loader
+ifneq ($(CONFIG_mips)$(CONFIG_mipsel),)
+  define Host/Configure/lzma
+	$(CP) \
+		$(HOST_BUILD_DIR)/arch/mips/include/asm/asm.h \
+		$(HOST_BUILD_DIR)/arch/mips/include/asm/regdef.h \
+		$(HOST_BUILD_DIR)/arch/mips/include/asm/asm-eva.h \
+		$(HOST_BUILD_DIR)/arch/mips/include/asm/isa-rev.h \
+		$(BUILD_DIR_TOOLCHAIN)/linux-dev/include/asm/
+  endef
+endif
+
+define Host/Configure/post/mips
+	$(call Host/Configure/lzma)
+endef
+
+define Host/Configure/post/mipsel
+	$(call Host/Configure/lzma)
+endef
+
+define Host/Prepare
+	rm -rf $(BUILD_DIR_TOOLCHAIN)/linux-*
+	$(call Kernel/Prepare/Default)
+	rm -f $(BUILD_DIR_TOOLCHAIN)/linux
+	ln -s linux-$(LINUX_VERSION) $(BUILD_DIR_TOOLCHAIN)/linux
+	$(SED) 's/@expr length/@-expr length/' $(HOST_BUILD_DIR)/Makefile
+endef
+
+define Host/Configure
+	yes '' | $(HOST_KMAKE) oldconfig
+	$(call Host/Configure/all)
+	$(call Host/Configure/post/$(ARCH))
+endef
+
+define Host/Compile
+endef
+
+define Host/Install
+	$(CP) $(BUILD_DIR_TOOLCHAIN)/linux-dev/* $(TOOLCHAIN_DIR)/
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(BUILD_DIR_TOOLCHAIN)/linux \
+		$(BUILD_DIR_TOOLCHAIN)/linux-dev
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/mold/Makefile b/toolchain/mold/Makefile
new file mode 100644
index 0000000..a2acba8
--- /dev/null
+++ b/toolchain/mold/Makefile
@@ -0,0 +1,22 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+define Host/Configure
+endef
+
+define Host/Compile
+endef
+
+define Host/Install
+	$(INSTALL_DIR) $(TOOLCHAIN_DIR)/bin
+	$(INSTALL_BIN) $(STAGING_DIR_HOST)/bin/mold $(TOOLCHAIN_DIR)/bin/$(REAL_GNU_TARGET_NAME)-ld.mold
+endef
+
+define Host/Clean
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/musl/Config.in b/toolchain/musl/Config.in
new file mode 100644
index 0000000..67ede4d
--- /dev/null
+++ b/toolchain/musl/Config.in
@@ -0,0 +1,13 @@
+# Password crypt stubbing
+
+config MUSL_DISABLE_CRYPT_SIZE_HACK
+	bool
+	prompt "Include crypt() support for SHA256, SHA512 and Blowfish ciphers" if TOOLCHAINOPTS
+	depends on USE_MUSL && !EXTERNAL_TOOLCHAIN
+	default y
+	help
+	  Enable this option to re-include crypt() support for the SHA256, SHA512 and
+	  Blowfish ciphers. Without this option, attempting to hash a string with a salt
+	  requesting one of these ciphers will cause the crypt() function to call stub
+	  implementations which will always fail with errno ENOSYS. Including the ciphers
+	  will increase the library size by about 14KB after LZMA compression.
diff --git a/toolchain/musl/Makefile b/toolchain/musl/Makefile
new file mode 100644
index 0000000..d441e37
--- /dev/null
+++ b/toolchain/musl/Makefile
@@ -0,0 +1,31 @@
+PATH_PREFIX=.
+
+include ./common.mk
+
+HOST_STAMP_BUILT:=$(HOST_BUILD_DIR)/.built
+HOST_STAMP_INSTALLED:=$(TOOLCHAIN_DIR)/stamp/.musl_installed
+
+HOST_BUILD_PARALLEL:=1
+
+MUSL_MAKEOPTS = -C $(HOST_BUILD_DIR) \
+	DESTDIR="$(TOOLCHAIN_DIR)/" \
+	LIBCC="$(shell $(TARGET_CC) -print-libgcc-file-name)"
+
+define Host/SetToolchainInfo
+	$(SED) 's,^\(LIBC_TYPE\)=.*,\1=$(PKG_NAME),' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_URL\)=.*,\1=http://www.musl-libc.org/,' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_VERSION\)=.*,\1=$(PKG_VERSION),' $(TOOLCHAIN_DIR)/info.mk
+	$(SED) 's,^\(LIBC_SO_VERSION\)=.*,\1=$(LIBC_SO_VERSION),' $(TOOLCHAIN_DIR)/info.mk
+endef
+
+define Host/Compile
+	+$(MAKE) $(HOST_JOBS) $(MUSL_MAKEOPTS) all
+endef
+
+define Host/Install
+	$(call Host/SetToolchainInfo)
+	+$(MAKE) $(HOST_JOBS) $(MUSL_MAKEOPTS) DESTDIR="$(TOOLCHAIN_DIR)/" install
+	$(CP) ./include $(TOOLCHAIN_DIR)/
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/musl/common.mk b/toolchain/musl/common.mk
new file mode 100644
index 0000000..35bdfd1
--- /dev/null
+++ b/toolchain/musl/common.mk
@@ -0,0 +1,56 @@
+#
+# Copyright (C) 2012-2013 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/target.mk
+
+PKG_NAME:=musl
+PKG_VERSION:=1.2.5
+PKG_RELEASE:=1
+
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_SOURCE_URL:=https://musl.libc.org/releases/
+PKG_HASH:=a9a118bbe84d8764da0ea0d28b3ab3fae8477fc7e4085d90102b8596fc7c75e4
+PKG_CPE_ID:=cpe:/a:musl-libc:musl
+
+LIBC_SO_VERSION:=$(PKG_VERSION)
+PATCH_DIR:=$(PATH_PREFIX)/patches
+
+BUILD_DIR_HOST:=$(BUILD_DIR_TOOLCHAIN)
+HOST_BUILD_PREFIX:=$(TOOLCHAIN_DIR)
+HOST_BUILD_DIR:=$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)-$(PKG_VERSION)
+
+include $(INCLUDE_DIR)/host-build.mk
+include $(INCLUDE_DIR)/hardening.mk
+
+TARGET_CFLAGS:= $(filter-out -O%,$(TARGET_CFLAGS))
+TARGET_CFLAGS+= $(if $(CONFIG_MUSL_DISABLE_CRYPT_SIZE_HACK),,-DCRYPT_SIZE_HACK)
+
+MUSL_CONFIGURE:= \
+	$(TARGET_CONFIGURE_OPTS) \
+	CFLAGS="$(TARGET_CFLAGS)" \
+	CROSS_COMPILE="$(TARGET_CROSS)" \
+	$(HOST_BUILD_DIR)/configure \
+		--prefix=/ \
+		--host=$(GNU_HOST_NAME) \
+		--target=$(REAL_GNU_TARGET_NAME) \
+		--disable-gcc-wrapper \
+		--enable-debug \
+		--enable-optimize
+
+define Host/Configure
+	ln -snf $(PKG_NAME)-$(PKG_VERSION) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+	( cd $(HOST_BUILD_DIR); rm -f config.cache; \
+		$(MUSL_CONFIGURE) \
+	);
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME) \
+		$(BUILD_DIR_TOOLCHAIN)/$(LIBC)-dev
+endef
diff --git a/toolchain/musl/include/sys/queue.h b/toolchain/musl/include/sys/queue.h
new file mode 100644
index 0000000..daf4553
--- /dev/null
+++ b/toolchain/musl/include/sys/queue.h
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef	_SYS_QUEUE_H_
+#define	_SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The
+ * elements are singly linked for minimum space and pointer manipulation
+ * overhead at the expense of O(n) removal for arbitrary elements. New
+ * elements can be added to the list after an existing element or at the
+ * head of the list.  Elements being removed from the head of the list
+ * should use the explicit macro for this purpose for optimum
+ * efficiency. A singly-linked list may only be traversed in the forward
+ * direction.  Singly-linked lists are ideal for applications with large
+ * datasets and few or no removals or for implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * List definitions.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+#define	LIST_INIT(head) do {						\
+	(head)->lh_first = NULL;					\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
+		(listelm)->field.le_next->field.le_prev =		\
+		    &(elm)->field.le_next;				\
+	(listelm)->field.le_next = (elm);				\
+	(elm)->field.le_prev = &(listelm)->field.le_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	(elm)->field.le_next = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &(elm)->field.le_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
+		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+	(head)->lh_first = (elm);					\
+	(elm)->field.le_prev = &(head)->lh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if ((elm)->field.le_next != NULL)				\
+		(elm)->field.le_next->field.le_prev = 			\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = (elm)->field.le_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = ((head)->lh_first);				\
+		(var);							\
+		(var) = ((var)->field.le_next))
+
+/*
+ * List access methods.
+ */
+#define	LIST_EMPTY(head)		((head)->lh_first == NULL)
+#define	LIST_FIRST(head)		((head)->lh_first)
+#define	LIST_NEXT(elm, field)		((elm)->field.le_next)
+
+
+/*
+ * Singly-linked List definitions.
+ */
+#define	SLIST_HEAD(name, type)						\
+struct name {								\
+	struct type *slh_first;	/* first element */			\
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	SLIST_ENTRY(type)						\
+struct {								\
+	struct type *sle_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define	SLIST_INIT(head) do {						\
+	(head)->slh_first = NULL;					\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
+	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
+	(slistelm)->field.sle_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.sle_next = (head)->slh_first;			\
+	(head)->slh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_REMOVE_HEAD(head, field) do {				\
+	(head)->slh_first = (head)->slh_first->field.sle_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_REMOVE(head, elm, type, field) do {			\
+	if ((head)->slh_first == (elm)) {				\
+		SLIST_REMOVE_HEAD((head), field);			\
+	}								\
+	else {								\
+		struct type *curelm = (head)->slh_first;		\
+		while(curelm->field.sle_next != (elm))			\
+			curelm = curelm->field.sle_next;		\
+		curelm->field.sle_next =				\
+		    curelm->field.sle_next->field.sle_next;		\
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	SLIST_FOREACH(var, head, field)					\
+	for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
+
+/*
+ * Singly-linked List access methods.
+ */
+#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
+#define	SLIST_FIRST(head)	((head)->slh_first)
+#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)					\
+struct name {								\
+	struct type *stqh_first;	/* first element */			\
+	struct type **stqh_last;	/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_INIT(head) do {						\
+	(head)->stqh_first = NULL;					\
+	(head)->stqh_last = &(head)->stqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(head)->stqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.stqe_next = NULL;					\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &(elm)->field.stqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
+		(head)->stqh_last = &(elm)->field.stqe_next;		\
+	(listelm)->field.stqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
+		(head)->stqh_last = &(head)->stqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->stqh_first == (elm)) {				\
+		STAILQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->stqh_first;		\
+		while (curelm->field.stqe_next != (elm))			\
+			curelm = curelm->field.stqe_next;		\
+		if ((curelm->field.stqe_next =				\
+			curelm->field.stqe_next->field.stqe_next) == NULL) \
+			    (head)->stqh_last = &(curelm)->field.stqe_next; \
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->stqh_first);				\
+		(var);							\
+		(var) = ((var)->field.stqe_next))
+
+#define	STAILQ_CONCAT(head1, head2) do {				\
+	if (!STAILQ_EMPTY((head2))) {					\
+		*(head1)->stqh_last = (head2)->stqh_first;		\
+		(head1)->stqh_last = (head2)->stqh_last;		\
+		STAILQ_INIT((head2));					\
+	}								\
+} while (/*CONSTCOND*/0)
+
+/*
+ * Singly-linked Tail queue access methods.
+ */
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+
+/*
+ * Simple queue definitions.
+ */
+#define	SIMPLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *sqh_first;	/* first element */			\
+	struct type **sqh_last;	/* addr of last next element */		\
+}
+
+#define	SIMPLEQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).sqh_first }
+
+#define	SIMPLEQ_ENTRY(type)						\
+struct {								\
+	struct type *sqe_next;	/* next element */			\
+}
+
+/*
+ * Simple queue functions.
+ */
+#define	SIMPLEQ_INIT(head) do {						\
+	(head)->sqh_first = NULL;					\
+	(head)->sqh_last = &(head)->sqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(head)->sqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.sqe_next = NULL;					\
+	*(head)->sqh_last = (elm);					\
+	(head)->sqh_last = &(elm)->field.sqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+		(head)->sqh_last = &(elm)->field.sqe_next;		\
+	(listelm)->field.sqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_REMOVE_HEAD(head, field) do {				\
+	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
+		(head)->sqh_last = &(head)->sqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_REMOVE(head, elm, type, field) do {			\
+	if ((head)->sqh_first == (elm)) {				\
+		SIMPLEQ_REMOVE_HEAD((head), field);			\
+	} else {							\
+		struct type *curelm = (head)->sqh_first;		\
+		while (curelm->field.sqe_next != (elm))			\
+			curelm = curelm->field.sqe_next;		\
+		if ((curelm->field.sqe_next =				\
+			curelm->field.sqe_next->field.sqe_next) == NULL) \
+			    (head)->sqh_last = &(curelm)->field.sqe_next; \
+	}								\
+} while (/*CONSTCOND*/0)
+
+#define	SIMPLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->sqh_first);				\
+		(var);							\
+		(var) = ((var)->field.sqe_next))
+
+/*
+ * Simple queue access methods.
+ */
+#define	SIMPLEQ_EMPTY(head)		((head)->sqh_first == NULL)
+#define	SIMPLEQ_FIRST(head)		((head)->sqh_first)
+#define	SIMPLEQ_NEXT(elm, field)	((elm)->field.sqe_next)
+
+
+/*
+ * Tail queue definitions.
+ */
+#define	_TAILQ_HEAD(name, type, qual)					\
+struct name {								\
+	qual type *tqh_first;		/* first element */		\
+	qual type *qual *tqh_last;	/* addr of last next element */	\
+}
+#define TAILQ_HEAD(name, type)	_TAILQ_HEAD(name, struct type,)
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	_TAILQ_ENTRY(type, qual)					\
+struct {								\
+	qual type *tqe_next;		/* next element */		\
+	qual type *qual *tqe_prev;	/* address of previous next element */\
+}
+#define TAILQ_ENTRY(type)	_TAILQ_ENTRY(struct type,)
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_INIT(head) do {						\
+	(head)->tqh_first = NULL;					\
+	(head)->tqh_last = &(head)->tqh_first;				\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
+		(head)->tqh_first->field.tqe_prev =			\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(head)->tqh_first = (elm);					\
+	(elm)->field.tqe_prev = &(head)->tqh_first;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.tqe_next = NULL;					\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &(elm)->field.tqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    &(elm)->field.tqe_next;				\
+	else								\
+		(head)->tqh_last = &(elm)->field.tqe_next;		\
+	(listelm)->field.tqe_next = (elm);				\
+	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	(elm)->field.tqe_next = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if (((elm)->field.tqe_next) != NULL)				\
+		(elm)->field.tqe_next->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
+} while (/*CONSTCOND*/0)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = ((head)->tqh_first);				\
+		(var);							\
+		(var) = ((var)->field.tqe_next))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));	\
+		(var);							\
+		(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
+
+#define	TAILQ_CONCAT(head1, head2, field) do {				\
+	if (!TAILQ_EMPTY(head2)) {					\
+		*(head1)->tqh_last = (head2)->tqh_first;		\
+		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
+		(head1)->tqh_last = (head2)->tqh_last;			\
+		TAILQ_INIT((head2));					\
+	}								\
+} while (/*CONSTCOND*/0)
+
+/*
+ * Tail queue access methods.
+ */
+#define	TAILQ_EMPTY(head)		((head)->tqh_first == NULL)
+#define	TAILQ_FIRST(head)		((head)->tqh_first)
+#define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
+
+#define	TAILQ_LAST(head, headname) \
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+#define	TAILQ_PREV(elm, headname, field) \
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+
+/*
+ * Circular queue definitions.
+ */
+#define	CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ (void *)&head, (void *)&head }
+
+#define	CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_INIT(head) do {						\
+	(head)->cqh_first = (void *)(head);				\
+	(head)->cqh_last = (void *)(head);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
+	(elm)->field.cqe_prev = (listelm);				\
+	if ((listelm)->field.cqe_next == (void *)(head))		\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
+	(listelm)->field.cqe_next = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	(elm)->field.cqe_next = (listelm);				\
+	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
+	if ((listelm)->field.cqe_prev == (void *)(head))		\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
+	(listelm)->field.cqe_prev = (elm);				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	(elm)->field.cqe_next = (head)->cqh_first;			\
+	(elm)->field.cqe_prev = (void *)(head);				\
+	if ((head)->cqh_last == (void *)(head))				\
+		(head)->cqh_last = (elm);				\
+	else								\
+		(head)->cqh_first->field.cqe_prev = (elm);		\
+	(head)->cqh_first = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	(elm)->field.cqe_next = (void *)(head);				\
+	(elm)->field.cqe_prev = (head)->cqh_last;			\
+	if ((head)->cqh_first == (void *)(head))			\
+		(head)->cqh_first = (elm);				\
+	else								\
+		(head)->cqh_last->field.cqe_next = (elm);		\
+	(head)->cqh_last = (elm);					\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if ((elm)->field.cqe_next == (void *)(head))			\
+		(head)->cqh_last = (elm)->field.cqe_prev;		\
+	else								\
+		(elm)->field.cqe_next->field.cqe_prev =			\
+		    (elm)->field.cqe_prev;				\
+	if ((elm)->field.cqe_prev == (void *)(head))			\
+		(head)->cqh_first = (elm)->field.cqe_next;		\
+	else								\
+		(elm)->field.cqe_prev->field.cqe_next =			\
+		    (elm)->field.cqe_next;				\
+} while (/*CONSTCOND*/0)
+
+#define	CIRCLEQ_FOREACH(var, head, field)				\
+	for ((var) = ((head)->cqh_first);				\
+		(var) != (const void *)(head);				\
+		(var) = ((var)->field.cqe_next))
+
+#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for ((var) = ((head)->cqh_last);				\
+		(var) != (const void *)(head);				\
+		(var) = ((var)->field.cqe_prev))
+
+/*
+ * Circular queue access methods.
+ */
+#define	CIRCLEQ_EMPTY(head)		((head)->cqh_first == (void *)(head))
+#define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
+#define	CIRCLEQ_LAST(head)		((head)->cqh_last)
+#define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
+#define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
+
+#define CIRCLEQ_LOOP_NEXT(head, elm, field)				\
+	(((elm)->field.cqe_next == (void *)(head))			\
+	    ? ((head)->cqh_first)					\
+	    : (elm->field.cqe_next))
+#define CIRCLEQ_LOOP_PREV(head, elm, field)				\
+	(((elm)->field.cqe_prev == (void *)(head))			\
+	    ? ((head)->cqh_last)					\
+	    : (elm->field.cqe_prev))
+
+#endif	/* sys/queue.h */
diff --git a/toolchain/musl/patches/110-read_timezone_from_fs.patch b/toolchain/musl/patches/110-read_timezone_from_fs.patch
new file mode 100644
index 0000000..c6d5d90
--- /dev/null
+++ b/toolchain/musl/patches/110-read_timezone_from_fs.patch
@@ -0,0 +1,97 @@
+--- a/src/time/__tz.c
++++ b/src/time/__tz.c
+@@ -5,6 +5,10 @@
+ #include <string.h>
+ #include <sys/mman.h>
+ #include <ctype.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
+ #include "libc.h"
+ #include "lock.h"
+ #include "fork_impl.h"
+@@ -123,6 +127,67 @@ static size_t zi_dotprod(const unsigned
+ 	return y;
+ }
+ 
++#define TZ_BUFLEN		(2*TZNAME_MAX + 56)
++static char *read_TZ_file(char *buf)
++{
++	int r;
++	int fd;
++	char *p = NULL;
++
++	fd = open("/etc/TZ", O_RDONLY);
++	if (fd >= 0) {
++		/* Shorter, and does one fewer read syscall */
++		r = read(fd, buf, TZ_BUFLEN);
++		if (r < 0)
++			goto ERROR;
++		p = buf + r;
++
++		if ((p > buf) && (p[-1] == '\n')) { /* Must end with newline */
++			p[-1] = 0;
++			p = buf;
++		} else {
++ERROR:
++			p = NULL;
++		}
++		close(fd);
++	} else {
++		fd = open("/etc/localtime", O_RDONLY);
++		if (fd >= 0) {
++			r = read(fd, buf, TZ_BUFLEN);
++			if (r != TZ_BUFLEN
++			 || strncmp(buf, "TZif", 4) != 0
++			 || (unsigned char)buf[4] < 2
++			 || lseek(fd, -TZ_BUFLEN, SEEK_END) < 0
++			) {
++				goto ERROR;
++			}
++			/* tzfile.h from tzcode database says about TZif2+ files:
++			**
++			** If tzh_version is '2' or greater, the above is followed by a second instance
++			** of tzhead and a second instance of the data in which each coded transition
++			** time uses 8 rather than 4 chars,
++			** then a POSIX-TZ-environment-variable-style string for use in handling
++			** instants after the last transition time stored in the file
++			** (with nothing between the newlines if there is no POSIX representation for
++			** such instants).
++			*/
++			r = read(fd, buf, TZ_BUFLEN);
++			if (r <= 0 || buf[--r] != '\n')
++				goto ERROR;
++			buf[r] = 0;
++			while (r != 0) {
++				if (buf[--r] == '\n') {
++					p = buf + r + 1;
++					break;
++				}
++			} /* else ('\n' not found): p remains NULL */
++			close(fd);
++		}
++	}
++
++	return p;
++}
++
+ static void do_tzset()
+ {
+ 	char buf[NAME_MAX+25], *pathname=buf+24;
+@@ -131,8 +196,15 @@ static void do_tzset()
+ 	size_t i;
+ 	static const char search[] =
+ 		"/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";
++	char tzbuf[TZ_BUFLEN];
+ 
+ 	s = getenv("TZ");
++
++	/* if TZ is empty try to read it from /etc/TZ */
++	if (!s || !*s) {
++		s = read_TZ_file(tzbuf);
++	}
++
+ 	if (!s) s = "/etc/localtime";
+ 	if (!*s) s = __utc;
+ 
diff --git a/toolchain/musl/patches/200-add_libssp_nonshared.patch b/toolchain/musl/patches/200-add_libssp_nonshared.patch
new file mode 100644
index 0000000..26a9bfe
--- /dev/null
+++ b/toolchain/musl/patches/200-add_libssp_nonshared.patch
@@ -0,0 +1,53 @@
+From 7ec87fbbc3cac99b4173d082dd6195f47c9a32e7 Mon Sep 17 00:00:00 2001
+From: Steven Barth <steven@midlink.org>
+Date: Mon, 22 Jun 2015 11:01:56 +0200
+Subject: [PATCH] Add libssp_nonshared.a so GCC's is not needed
+
+Signed-off-by: Steven Barth <steven@midlink.org>
+
+--- a/Makefile
++++ b/Makefile
+@@ -67,7 +67,7 @@ CRT_LIBS = $(addprefix lib/,$(notdir $(C
+ STATIC_LIBS = lib/libc.a
+ SHARED_LIBS = lib/libc.so
+ TOOL_LIBS = lib/musl-gcc.specs
+-ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS)
++ALL_LIBS = $(CRT_LIBS) $(STATIC_LIBS) $(SHARED_LIBS) $(EMPTY_LIBS) $(TOOL_LIBS) lib/libssp_nonshared.a
+ ALL_TOOLS = obj/musl-gcc
+ 
+ WRAPCC_GCC = gcc
+@@ -88,7 +88,7 @@ else
+ 
+ all: $(ALL_LIBS) $(ALL_TOOLS)
+ 
+-OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include)
++OBJ_DIRS = $(sort $(patsubst %/,%,$(dir $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(GENH) $(GENH_INT))) obj/include obj/libssp_nonshared)
+ 
+ $(ALL_LIBS) $(ALL_TOOLS) $(ALL_OBJS) $(ALL_OBJS:%.o=%.lo) $(GENH) $(GENH_INT): | $(OBJ_DIRS)
+ 
+@@ -115,6 +115,8 @@ obj/crt/rcrt1.o: $(srcdir)/ldso/dlstart.
+ 
+ obj/crt/Scrt1.o obj/crt/rcrt1.o: CFLAGS_ALL += -fPIC
+ 
++obj/libssp_nonshared/__stack_chk_fail_local.o: CFLAGS_ALL += $(CFLAGS_NOSSP)
++
+ OPTIMIZE_SRCS = $(wildcard $(OPTIMIZE_GLOBS:%=$(srcdir)/src/%))
+ $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.o) $(OPTIMIZE_SRCS:$(srcdir)/%.c=obj/%.lo): CFLAGS += -O3
+ 
+@@ -167,6 +169,11 @@ lib/libc.a: $(AOBJS)
+ 	$(AR) rc $@ $(AOBJS)
+ 	$(RANLIB) $@
+ 
++lib/libssp_nonshared.a: obj/libssp_nonshared/__stack_chk_fail_local.o
++	rm -f $@
++	$(AR) rc $@ $<
++	$(RANLIB) $@
++
+ $(EMPTY_LIBS):
+ 	rm -f $@
+ 	$(AR) rc $@
+--- /dev/null
++++ b/libssp_nonshared/__stack_chk_fail_local.c
+@@ -0,0 +1,2 @@
++#include "atomic.h"
++void __attribute__((visibility ("hidden"))) __stack_chk_fail_local(void) { a_crash(); }
diff --git a/toolchain/musl/patches/300-relative.patch b/toolchain/musl/patches/300-relative.patch
new file mode 100644
index 0000000..7e1eb7d
--- /dev/null
+++ b/toolchain/musl/patches/300-relative.patch
@@ -0,0 +1,11 @@
+--- a/Makefile
++++ b/Makefile
+@@ -217,7 +217,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc
+ 	$(INSTALL) -D -m 644 $< $@
+ 
+ $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
+-	$(INSTALL) -D -l $(libdir)/libc.so $@ || true
++	$(INSTALL) -D -l libc.so $@ || true
+ 
+ install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
+ 
diff --git a/toolchain/musl/patches/400-fix-loongarch64-ldso-file-name.patch b/toolchain/musl/patches/400-fix-loongarch64-ldso-file-name.patch
new file mode 100644
index 0000000..a19ceb4
--- /dev/null
+++ b/toolchain/musl/patches/400-fix-loongarch64-ldso-file-name.patch
@@ -0,0 +1,10 @@
+--- a/Makefile
++++ b/Makefile
+@@ -218,6 +218,7 @@ $(DESTDIR)$(includedir)/%: $(srcdir)/inc
+ 
+ $(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
+ 	$(INSTALL) -D -l libc.so $@ || true
++	$(if $(filter loongarch64,$(ARCH)$(SUBARCH)),$(INSTALL) -D -l libc.so $(subst $(ARCH)$(SUBARCH).so.1,loongarch-lp64d.so.1,$@) || true)
+ 
+ install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
+ 
diff --git a/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch b/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch
new file mode 100644
index 0000000..7a1ab3f
--- /dev/null
+++ b/toolchain/musl/patches/600-nftw-support-common-gnu-extension.patch
@@ -0,0 +1,95 @@
+From 6f1143425a3afc4eb5086e9c90e7efb3affd7cb7 Mon Sep 17 00:00:00 2001
+From: Tony Ambardar <Tony.Ambardar@gmail.com>
+Date: Sat, 11 Jul 2020 06:35:46 -0700
+Subject: [PATCH 2/2] nftw: support common gnu extension
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+---
+ include/ftw.h   |  8 ++++++++
+ src/misc/nftw.c | 35 ++++++++++++++++++++++++++++++-----
+ 2 files changed, 38 insertions(+), 5 deletions(-)
+
+--- a/include/ftw.h
++++ b/include/ftw.h
+@@ -21,6 +21,14 @@ extern "C" {
+ #define FTW_CHDIR 4
+ #define FTW_DEPTH 8
+ 
++#ifdef _GNU_SOURCE
++#define FTW_ACTIONRETVAL 16
++#define FTW_CONTINUE 0
++#define FTW_STOP 1
++#define FTW_SKIP_SUBTREE 2
++#define FTW_SKIP_SIBLINGS 3
++#endif
++
+ struct FTW {
+ 	int base;
+ 	int level;
+--- a/src/misc/nftw.c
++++ b/src/misc/nftw.c
+@@ -1,3 +1,4 @@
++#define _GNU_SOURCE
+ #include <ftw.h>
+ #include <dirent.h>
+ #include <fcntl.h>
+@@ -74,8 +75,20 @@ static int do_nftw(char *path, int (*fn)
+ 		if (!fd_limit) close(dfd);
+ 	}
+ 
+-	if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+-		return r;
++	if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) {
++		if (flags & FTW_ACTIONRETVAL)
++			switch (r) {
++			case FTW_SKIP_SUBTREE:
++				h = NULL;
++			case FTW_CONTINUE:
++				break;
++			case FTW_SKIP_SIBLINGS:
++			case FTW_STOP:
++				return r;
++			}
++		else
++			return r;
++	}
+ 
+ 	for (; h; h = h->chain)
+ 		if (h->dev == st.st_dev && h->ino == st.st_ino)
+@@ -103,7 +116,10 @@ static int do_nftw(char *path, int (*fn)
+ 				strcpy(path+j+1, de->d_name);
+ 				if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
+ 					closedir(d);
+-					return r;
++					if ((flags & FTW_ACTIONRETVAL) && r == FTW_SKIP_SIBLINGS)
++						break;
++					else
++						return r;
+ 				}
+ 			}
+ 			closedir(d);
+@@ -114,8 +130,16 @@ static int do_nftw(char *path, int (*fn)
+ 	}
+ 
+ 	path[l] = 0;
+-	if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+-		return r;
++	if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev))) {
++		if (flags & FTW_ACTIONRETVAL)
++			switch (r) {
++				case FTW_SKIP_SIBLINGS:
++				case FTW_STOP:
++					return r;
++			}
++		else
++			return r;
++	}
+ 
+ 	return 0;
+ }
+@@ -140,3 +164,5 @@ int nftw(const char *path, int (*fn)(con
+ 	pthread_setcancelstate(cs, 0);
+ 	return r;
+ }
++
++#undef nftw64
diff --git a/toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch b/toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch
new file mode 100644
index 0000000..1677693
--- /dev/null
+++ b/toolchain/musl/patches/610-add-renameat2-linux-syscall-wrapper.patch
@@ -0,0 +1,61 @@
+From dc651fe2e6b16087c519c0bd0bf943cb7c53c807 Mon Sep 17 00:00:00 2001
+In-Reply-To: <20240423234355.2414567-1-Tony.Ambardar@gmail.com>
+References: <20240423234355.2414567-1-Tony.Ambardar@gmail.com>
+From: Tony Ambardar <Tony.Ambardar@gmail.com>
+Date: Sat, 20 Apr 2024 21:30:13 -0700
+Subject: [PATCH v3] add renameat2 linux syscall wrapper
+To: musl@lists.openwall.com
+Cc: Rich Felker <dalias@libc.org>
+
+This syscall is available since Linux 3.15 and also implemented in glibc
+from version 2.28. It is commonly used in filesystem or security contexts.
+
+Constants RENAME_NOREPLACE, RENAME_EXCHANGE, RENAME_WHITEOUT are guarded by
+_GNU_SOURCE as with glibc.
+
+Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
+---
+v2 -> v3:
+ * call SYS_renameat first if applicable
+ * drop unneeded error code handling
+
+v1 -> v2:
+ * align related constants
+ * drop 'int' from 'unsigned int'
+ * add fallback to SYS_renameat where applicable
+---
+ include/stdio.h       |  7 +++++++
+ src/linux/renameat2.c | 11 +++++++++++
+ 2 files changed, 18 insertions(+)
+ create mode 100644 src/linux/renameat2.c
+
+--- a/include/stdio.h
++++ b/include/stdio.h
+@@ -158,6 +158,13 @@ char *ctermid(char *);
+ #define L_ctermid 20
+ #endif
+ 
++#if defined(_GNU_SOURCE)
++#define RENAME_NOREPLACE (1 << 0)
++#define RENAME_EXCHANGE  (1 << 1)
++#define RENAME_WHITEOUT  (1 << 2)
++
++int renameat2(int, const char *, int, const char *, unsigned);
++#endif
+ 
+ #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
+  || defined(_BSD_SOURCE)
+--- /dev/null
++++ b/src/linux/renameat2.c
+@@ -0,0 +1,11 @@
++#define _GNU_SOURCE
++#include <stdio.h>
++#include "syscall.h"
++
++int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags)
++{
++#ifdef SYS_renameat
++	if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new);
++#endif
++	return syscall(SYS_renameat2, oldfd, old, newfd, new, flags);
++}
diff --git a/toolchain/musl/patches/900-iconv_size_hack.patch b/toolchain/musl/patches/900-iconv_size_hack.patch
new file mode 100644
index 0000000..ad1dc4b
--- /dev/null
+++ b/toolchain/musl/patches/900-iconv_size_hack.patch
@@ -0,0 +1,100 @@
+--- a/src/locale/iconv.c
++++ b/src/locale/iconv.c
+@@ -48,6 +48,7 @@ static const unsigned char charmaps[] =
+ "utf16\0\0\312"
+ "ucs4\0utf32\0\0\313"
+ "ucs2\0\0\314"
++#ifdef FULL_ICONV
+ "eucjp\0\0\320"
+ "shiftjis\0sjis\0cp932\0\0\321"
+ "iso2022jp\0\0\322"
+@@ -56,6 +57,7 @@ static const unsigned char charmaps[] =
+ "gb2312\0\0\332"
+ "big5\0bigfive\0cp950\0big5hkscs\0\0\340"
+ "euckr\0ksc5601\0ksx1001\0cp949\0\0\350"
++#endif
+ #include "codepages.h"
+ ;
+ 
+@@ -66,6 +68,7 @@ static const unsigned short legacy_chars
+ #include "legacychars.h"
+ };
+ 
++#ifdef FULL_ICONV
+ static const unsigned short jis0208[84][94] = {
+ #include "jis0208.h"
+ };
+@@ -85,6 +88,7 @@ static const unsigned short hkscs[] = {
+ static const unsigned short ksc[93][94] = {
+ #include "ksc.h"
+ };
++#endif
+ 
+ static const unsigned short rev_jis[] = {
+ #include "revjis.h"
+@@ -205,6 +209,7 @@ static unsigned legacy_map(const unsigne
+ 	return x < 256 ? x : legacy_chars[x-256];
+ }
+ 
++#ifdef FULL_ICONV
+ static unsigned uni_to_jis(unsigned c)
+ {
+ 	unsigned nel = sizeof rev_jis / sizeof *rev_jis;
+@@ -223,6 +228,7 @@ static unsigned uni_to_jis(unsigned c)
+ 		}
+ 	}
+ }
++#endif
+ 
+ size_t iconv(iconv_t cd, char **restrict in, size_t *restrict inb, char **restrict out, size_t *restrict outb)
+ {
+@@ -319,6 +325,7 @@ size_t iconv(iconv_t cd, char **restrict
+ 			}
+ 			type = scd->state;
+ 			continue;
++#ifdef FULL_ICONV
+ 		case SHIFT_JIS:
+ 			if (c < 128) break;
+ 			if (c-0xa1 <= 0xdf-0xa1) {
+@@ -518,6 +525,7 @@ size_t iconv(iconv_t cd, char **restrict
+ 			c = ksc[c][d];
+ 			if (!c) goto ilseq;
+ 			break;
++#endif
+ 		default:
+ 			if (!c) break;
+ 			c = legacy_map(map, c);
+@@ -559,6 +567,7 @@ size_t iconv(iconv_t cd, char **restrict
+ 				}
+ 			}
+ 			goto subst;
++#ifdef FULL_ICONV
+ 		case SHIFT_JIS:
+ 			if (c < 128) goto revout;
+ 			if (c == 0xa5) {
+@@ -632,6 +641,7 @@ size_t iconv(iconv_t cd, char **restrict
+ 			*(*out)++ = 'B';
+ 			*outb -= 8;
+ 			break;
++#endif
+ 		case UCS2:
+ 			totype = UCS2BE;
+ 		case UCS2BE:
+--- a/src/locale/codepages.h
++++ b/src/locale/codepages.h
+@@ -129,6 +129,7 @@
+ "\340\204\43\316\100\344\34\144\316\71\350\244\243\316\72\354\264\343\316\73"
+ "\21\361\44\317\74\364\30\145\17\124\146\345\243\317\76\374\134\304\327\77"
+ 
++#ifdef FULL_ICONV
+ "cp1250\0"
+ "windows1250\0"
+ "\0\40"
+@@ -239,6 +240,7 @@
+ "\20\105\163\330\64\324\324\145\315\65\330\144\243\315\66\334\334\145\330\67"
+ "\340\204\43\316\100\344\224\143\316\71\350\244\243\316\72\205\265\343\316\73"
+ "\21\305\203\330\74\364\330\145\317\75\370\344\243\317\76\374\340\65\362\77"
++#endif
+ 
+ "koi8r\0"
+ "\0\40"
diff --git a/toolchain/musl/patches/901-crypt_size_hack.patch b/toolchain/musl/patches/901-crypt_size_hack.patch
new file mode 100644
index 0000000..667894a
--- /dev/null
+++ b/toolchain/musl/patches/901-crypt_size_hack.patch
@@ -0,0 +1,75 @@
+--- a/src/crypt/crypt_sha512.c
++++ b/src/crypt/crypt_sha512.c
+@@ -13,6 +13,17 @@
+ #include <string.h>
+ #include <stdint.h>
+ 
++#ifdef CRYPT_SIZE_HACK
++#include <errno.h>
++
++char *__crypt_sha512(const char *key, const char *setting, char *output)
++{
++	errno = ENOSYS;
++	return NULL;
++}
++
++#else
++
+ /* public domain sha512 implementation based on fips180-3 */
+ /* >=2^64 bits messages are not supported (about 2000 peta bytes) */
+ 
+@@ -369,3 +380,4 @@ char *__crypt_sha512(const char *key, co
+ 		return "*";
+ 	return p;
+ }
++#endif
+--- a/src/crypt/crypt_blowfish.c
++++ b/src/crypt/crypt_blowfish.c
+@@ -50,6 +50,17 @@
+ #include <string.h>
+ #include <stdint.h>
+ 
++#ifdef CRYPT_SIZE_HACK
++#include <errno.h>
++
++char *__crypt_blowfish(const char *key, const char *setting, char *output)
++{
++	errno = ENOSYS;
++	return NULL;
++}
++
++#else
++
+ typedef uint32_t BF_word;
+ typedef int32_t BF_word_signed;
+ 
+@@ -804,3 +815,4 @@ char *__crypt_blowfish(const char *key,
+ 
+ 	return "*";
+ }
++#endif
+--- a/src/crypt/crypt_sha256.c
++++ b/src/crypt/crypt_sha256.c
+@@ -13,6 +13,17 @@
+ #include <string.h>
+ #include <stdint.h>
+ 
++#ifdef CRYPT_SIZE_HACK
++#include <errno.h>
++
++char *__crypt_sha256(const char *key, const char *setting, char *output)
++{
++	errno = ENOSYS;
++	return NULL;
++}
++
++#else
++
+ /* public domain sha256 implementation based on fips180-3 */
+ 
+ struct sha256 {
+@@ -320,3 +331,4 @@ char *__crypt_sha256(const char *key, co
+ 		return "*";
+ 	return p;
+ }
++#endif
diff --git a/toolchain/musl/patches/999-libc-so-0-1.patch b/toolchain/musl/patches/999-libc-so-0-1.patch
new file mode 100644
index 0000000..d865690
--- /dev/null
+++ b/toolchain/musl/patches/999-libc-so-0-1.patch
@@ -0,0 +1,16 @@
+--- a/Makefile
++++ b/Makefile
+@@ -216,11 +216,11 @@ $(DESTDIR)$(includedir)/bits/%: obj/incl
+ $(DESTDIR)$(includedir)/%: $(srcdir)/include/%
+ 	$(INSTALL) -D -m 644 $< $@
+ 
+-$(DESTDIR)$(LDSO_PATHNAME): $(DESTDIR)$(libdir)/libc.so
++$(DESTDIR)$(LDSO_PATHNAME) $(DESTDIR)$(syslibdir)/libc.so.0 $(DESTDIR)$(syslibdir)/libc.so.1: $(DESTDIR)$(libdir)/libc.so
+ 	$(INSTALL) -D -l libc.so $@ || true
+ 	$(if $(filter loongarch64,$(ARCH)$(SUBARCH)),$(INSTALL) -D -l libc.so $(subst $(ARCH)$(SUBARCH).so.1,loongarch-lp64d.so.1,$@) || true)
+ 
+-install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME),)
++install-libs: $(ALL_LIBS:lib/%=$(DESTDIR)$(libdir)/%) $(if $(SHARED_LIBS),$(DESTDIR)$(LDSO_PATHNAME) $(DESTDIR)$(syslibdir)/libc.so.0 $(DESTDIR)$(syslibdir)/libc.so.1,)
+ 
+ install-headers: $(ALL_INCLUDES:include/%=$(DESTDIR)$(includedir)/%)
+ 
diff --git a/toolchain/nasm/Makefile b/toolchain/nasm/Makefile
new file mode 100644
index 0000000..bcdb293
--- /dev/null
+++ b/toolchain/nasm/Makefile
@@ -0,0 +1,53 @@
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=nasm
+PKG_VERSION:=2.16.03
+
+PKG_SOURCE_URL:=https://www.nasm.us/pub/nasm/releasebuilds/$(PKG_VERSION)/
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
+PKG_HASH:=5bc940dd8a4245686976a8f7e96ba9340a0915f2d5b88356874890e207bdb581
+PKG_CPE_ID:=cpe:/a:nasm:netwide_assembler
+
+HOST_BUILD_PARALLEL:=1
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+HOST_CONFIGURE_ARGS+= \
+		--target=$(REAL_GNU_TARGET_NAME) \
+		--with-sysroot=$(TOOLCHAIN_DIR) \
+		--disable-lto \
+		--disable-werror \
+		--disable-gdb \
+		$(SOFT_FLOAT_CONFIG_OPTION) \
+
+define Host/Prepare
+	$(call Host/Prepare/Default)
+	ln -snf $(notdir $(HOST_BUILD_DIR)) $(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+	$(CP) $(SCRIPT_DIR)/config.{guess,sub} $(HOST_BUILD_DIR)/
+endef
+
+define Host/Configure
+	(cd $(HOST_BUILD_DIR); \
+		./autogen.sh \
+	);
+	$(call Host/Configure/Default)
+endef
+
+define Host/Install
+	$(MAKE) -C $(HOST_BUILD_DIR) \
+		$(HOST_MAKE_FLAGS) \
+		prefix=$(TOOLCHAIN_DIR) \
+		install
+endef
+
+define Host/Clean
+	rm -rf \
+		$(HOST_BUILD_DIR) \
+		$(BUILD_DIR_TOOLCHAIN)/$(PKG_NAME)
+endef
+
+$(eval $(call HostBuild))
diff --git a/toolchain/wrapper/Makefile b/toolchain/wrapper/Makefile
new file mode 100644
index 0000000..e1f8389
--- /dev/null
+++ b/toolchain/wrapper/Makefile
@@ -0,0 +1,72 @@
+#
+# Copyright (C) 2012 OpenWrt.org
+#
+# This is free software, licensed under the GNU General Public License v2.
+# See /LICENSE for more information.
+#
+
+include $(TOPDIR)/rules.mk
+
+PKG_NAME:=wrapper
+PKG_VERSION:=1
+
+include $(INCLUDE_DIR)/toolchain-build.mk
+
+
+# 1: args
+define toolchain_util
+$(strip $(SCRIPT_DIR)/ext-toolchain.sh --toolchain $(CONFIG_TOOLCHAIN_ROOT) \
+	--cflags $(CONFIG_TARGET_OPTIMIZATION) \
+	--cflags "$(if $(call qstrip,$(CONFIG_TOOLCHAIN_LIBC)),-m$(call qstrip,$(CONFIG_TOOLCHAIN_LIBC))) $(if $(CONFIG_SOFT_FLOAT),-msoft-float)" \
+	--cflags "$(patsubst ./%,-I$(TOOLCHAIN_ROOT_DIR)/%,$(call qstrip,$(CONFIG_TOOLCHAIN_INC_PATH)))" \
+	--cflags "$(patsubst ./%,-L$(TOOLCHAIN_ROOT_DIR)/%,$(call qstrip,$(CONFIG_TOOLCHAIN_LIB_PATH)))" \
+	$(1))
+endef
+
+# 1: config symbol
+# 2: feature
+define toolchain_test
+$$(if $$($(1)), \
+	@echo -n "Testing external toolchain for $(2) support ... "; \
+	if $(call toolchain_util,--test "$(2)"); then \
+		echo "ok"; exit 0; \
+	else \
+		echo "failed"; \
+		echo "ERROR: $(1) is enabled but the external toolchain does not support it"; \
+		exit 1; \
+	fi)
+endef
+
+
+define Host/SetToolchainInfo
+	if [ -f $(CONFIG_TOOLCHAIN_ROOT)/info.mk ]; then \
+		$(CP) $(CONFIG_TOOLCHAIN_ROOT)/info.mk $(TOOLCHAIN_DIR)/; \
+	else \
+		$(SED) 's,GCC_VERSION=.*,GCC_VERSION=$(CONFIG_GCC_VERSION),' $(TOOLCHAIN_DIR)/info.mk; \
+	fi
+endef
+
+define Host/Prepare
+	$(call toolchain_test,CONFIG_SOFT_FLOAT,softfloat)
+	$(call toolchain_test,CONFIG_IPV6,ipv6)
+	$(call toolchain_test,CONFIG_NLS,wchar)
+	$(call toolchain_test,CONFIG_PACKAGE_libpthread,threads)
+endef
+
+define Host/Configure
+endef
+
+define Host/Compile
+endef
+
+define Host/Install
+	$(call toolchain_util,--wrap "$(TOOLCHAIN_DIR)/bin")
+	$(call Host/SetToolchainInfo)
+endef
+
+define Host/Clean
+	rm -rf $(TOOLCHAIN_DIR)/bin
+	rm -rf $(TOOLCHAIN_DIR)/info.mk
+endef
+
+$(eval $(call HostBuild))