pkgsrc-Changes archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
CVS commit: pkgsrc/cross/ppc-morphos-binutils
Module Name: pkgsrc
Committed By: js
Date: Sat Jun 13 15:32:45 UTC 2026
Modified Files:
pkgsrc/cross/ppc-morphos-binutils: Makefile PLIST distinfo
Added Files:
pkgsrc/cross/ppc-morphos-binutils/files: README
binutils-2.45.1-morphos.diff
Removed Files:
pkgsrc/cross/ppc-morphos-binutils/patches: patch-bfd_elf32-ppc.c
Log Message:
Update cross/ppc-morphos-binutils to 2.45.1
This updates to the version from the MorphOS 3.20 SDK.
To generate a diff of this commit:
cvs rdiff -u -r1.11 -r1.12 pkgsrc/cross/ppc-morphos-binutils/Makefile
cvs rdiff -u -r1.3 -r1.4 pkgsrc/cross/ppc-morphos-binutils/PLIST
cvs rdiff -u -r1.10 -r1.11 pkgsrc/cross/ppc-morphos-binutils/distinfo
cvs rdiff -u -r0 -r1.1 pkgsrc/cross/ppc-morphos-binutils/files/README \
pkgsrc/cross/ppc-morphos-binutils/files/binutils-2.45.1-morphos.diff
cvs rdiff -u -r1.1 -r0 \
pkgsrc/cross/ppc-morphos-binutils/patches/patch-bfd_elf32-ppc.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: pkgsrc/cross/ppc-morphos-binutils/Makefile
diff -u pkgsrc/cross/ppc-morphos-binutils/Makefile:1.11 pkgsrc/cross/ppc-morphos-binutils/Makefile:1.12
--- pkgsrc/cross/ppc-morphos-binutils/Makefile:1.11 Mon Apr 28 20:45:02 2025
+++ pkgsrc/cross/ppc-morphos-binutils/Makefile Sat Jun 13 15:32:44 2026
@@ -1,10 +1,9 @@
-# $NetBSD: Makefile,v 1.11 2025/04/28 20:45:02 js Exp $
+# $NetBSD: Makefile,v 1.12 2026/06/13 15:32:44 js Exp $
-DISTNAME= sdk-source-20230510
-PKGNAME= ppc-morphos-binutils-2.40
-PKGREVISION= 1
+DISTNAME= binutils-2.45.1
+PKGNAME= ppc-morphos-${DISTNAME}
CATEGORIES= cross
-MASTER_SITES= https://morphos-team.net/files/src/sdk/
+MASTER_SITES= ${MASTER_SITE_GNU:=binutils/}
EXTRACT_SUFX= .tar.xz
MAINTAINER= js%NetBSD.org@localhost
@@ -12,7 +11,6 @@ HOMEPAGE= https://www.morphos-team.net/
COMMENT= Binutils for ppc-morphos
LICENSE= gnu-gpl-v3
-WRKSRC= ${WRKDIR}/sdk-source/binutils/binutils-${PKGVERSION_NOREV}
GNU_CONFIGURE= yes
GNU_CONFIGURE_STRICT= no # several sub-configures know --enable-nls
USE_LANGUAGES= c c++
@@ -28,13 +26,8 @@ CONFIGURE_ARGS+= --disable-initfini-arra
CONFIGURE_ARGS+= --disable-nls
CONFIGURE_ARGS+= CFLAGS="${CFLAGS} -DMORPHOS_TARGET"
-post-extract:
- ${RUN} cd ${WRKDIR}/sdk-source/binutils && \
- ${XZCAT} binutils-${PKGVERSION_NOREV}.tar.xz | ${GTAR} xf -
-
pre-patch:
- ${RUN} cd ${WRKDIR}/sdk-source/binutils && \
- ${PATCH} -p0 <binutils-${PKGVERSION_NOREV}-morphos.diff
+ ${RUN} cd ${WRKSRC} && ${PATCH} -p1 <${FILESDIR}/binutils-2.45.1-morphos.diff
pre-configure:
${RUN} cd ${WRKSRC} && ${MKDIR} ${OBJDIR}
Index: pkgsrc/cross/ppc-morphos-binutils/PLIST
diff -u pkgsrc/cross/ppc-morphos-binutils/PLIST:1.3 pkgsrc/cross/ppc-morphos-binutils/PLIST:1.4
--- pkgsrc/cross/ppc-morphos-binutils/PLIST:1.3 Wed Mar 27 15:52:32 2024
+++ pkgsrc/cross/ppc-morphos-binutils/PLIST Sat Jun 13 15:32:44 2026
@@ -1,4 +1,4 @@
-@comment $NetBSD: PLIST,v 1.3 2024/03/27 15:52:32 js Exp $
+@comment $NetBSD: PLIST,v 1.4 2026/06/13 15:32:44 js Exp $
gg/bin/ppc-morphos-addr2line
gg/bin/ppc-morphos-ar
gg/bin/ppc-morphos-as
@@ -47,19 +47,23 @@ gg/ppc-morphos/bin/strip
gg/ppc-morphos/lib/ldscripts/morphos.x
gg/ppc-morphos/lib/ldscripts/morphos.xbn
gg/ppc-morphos/lib/ldscripts/morphos.xe
+gg/ppc-morphos/lib/ldscripts/morphos.xer
gg/ppc-morphos/lib/ldscripts/morphos.xn
gg/ppc-morphos/lib/ldscripts/morphos.xr
gg/ppc-morphos/lib/ldscripts/morphos.xu
gg/ppc-morphos/lib/ldscripts/morphos_baserel.x
gg/ppc-morphos/lib/ldscripts/morphos_baserel.xbn
gg/ppc-morphos/lib/ldscripts/morphos_baserel.xe
+gg/ppc-morphos/lib/ldscripts/morphos_baserel.xer
gg/ppc-morphos/lib/ldscripts/morphos_baserel.xn
gg/ppc-morphos/lib/ldscripts/morphos_baserel.xr
gg/ppc-morphos/lib/ldscripts/morphos_baserel.xu
+gg/ppc-morphos/lib/ldscripts/stamp
gg/share/info/as.info
gg/share/info/bfd.info
gg/share/info/binutils.info
gg/share/info/ctf-spec.info
gg/share/info/gprof.info
gg/share/info/ld.info
+gg/share/info/ldint.info
gg/share/info/sframe-spec.info
Index: pkgsrc/cross/ppc-morphos-binutils/distinfo
diff -u pkgsrc/cross/ppc-morphos-binutils/distinfo:1.10 pkgsrc/cross/ppc-morphos-binutils/distinfo:1.11
--- pkgsrc/cross/ppc-morphos-binutils/distinfo:1.10 Mon Apr 28 20:45:02 2025
+++ pkgsrc/cross/ppc-morphos-binutils/distinfo Sat Jun 13 15:32:44 2026
@@ -1,8 +1,7 @@
-$NetBSD: distinfo,v 1.10 2025/04/28 20:45:02 js Exp $
+$NetBSD: distinfo,v 1.11 2026/06/13 15:32:44 js Exp $
-BLAKE2s (sdk-source-20230510.tar.xz) = 777febe845ddbf50cbaec55c2d198085996a5064bc3c4128f44dfe79355d765e
-SHA512 (sdk-source-20230510.tar.xz) = badf3e678d514713ece14779dcce5fe78f3a849c73718e05b3317c1c766fb9879368c8fd58f9441c905023a660e893cf0eec405d2c133e4c6d11fe39acc50418
-Size (sdk-source-20230510.tar.xz) = 588551012 bytes
-SHA1 (patch-bfd_elf32-ppc.c) = ebea3d9292ca0b095e07726ca81729ab17a8bbfb
+BLAKE2s (binutils-2.45.1.tar.xz) = 7fe96d2c024eb442de382b51f3b8f4a410fdd3e33dba4c489e278908e3e3a3c0
+SHA512 (binutils-2.45.1.tar.xz) = ea030419eba387579ab717be7e3223fc99e93b586860b06003c12489f93441640d4082736f76aa5e98233db4f46e232f536a45e471486de1f5b64e1b827c167e
+Size (binutils-2.45.1.tar.xz) = 27962312 bytes
SHA1 (patch-bfd_sysdep.h) = 6dacf9e17529fd74c90a07b4531429fa3e33feb3
SHA1 (patch-zlib_zutil.c) = 00db854685510b1f52bdc62f996fb792bd46bd63
Added files:
Index: pkgsrc/cross/ppc-morphos-binutils/files/README
diff -u /dev/null pkgsrc/cross/ppc-morphos-binutils/files/README:1.1
--- /dev/null Sat Jun 13 15:32:45 2026
+++ pkgsrc/cross/ppc-morphos-binutils/files/README Sat Jun 13 15:32:44 2026
@@ -0,0 +1 @@
+These files are coming from the MorphOS 3.20 SDK.
Index: pkgsrc/cross/ppc-morphos-binutils/files/binutils-2.45.1-morphos.diff
diff -u /dev/null pkgsrc/cross/ppc-morphos-binutils/files/binutils-2.45.1-morphos.diff:1.1
--- /dev/null Sat Jun 13 15:32:45 2026
+++ pkgsrc/cross/ppc-morphos-binutils/files/binutils-2.45.1-morphos.diff Sat Jun 13 15:32:45 2026
@@ -0,0 +1,4945 @@
+diff -ruN binutils-2.45/bfd/bfd-in2.h binutils-2.45_mos/bfd/bfd-in2.h
+--- binutils-2.45/bfd/bfd-in2.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/bfd-in2.h 2025-07-27 14:39:08.700060484 +0300
+@@ -3975,6 +3975,10 @@
+ BFD_RELOC_PPC_EMB_RELST_HA,
+ BFD_RELOC_PPC_EMB_BIT_FLD,
+ BFD_RELOC_PPC_EMB_RELSDA,
++ BFD_RELOC_PPC_MORPHOS_DREL,
++ BFD_RELOC_PPC_MORPHOS_DREL_LO,
++ BFD_RELOC_PPC_MORPHOS_DREL_HI,
++ BFD_RELOC_PPC_MORPHOS_DREL_HA,
+ BFD_RELOC_PPC_VLE_REL8,
+ BFD_RELOC_PPC_VLE_REL15,
+ BFD_RELOC_PPC_VLE_REL24,
+diff -ruN binutils-2.45/bfd/config.bfd binutils-2.45_mos/bfd/config.bfd
+--- binutils-2.45/bfd/config.bfd 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/config.bfd 2025-07-27 14:39:08.700060484 +0300
+@@ -1208,6 +1208,12 @@
+ pru-*-*)
+ targ_defvec=pru_elf32_vec
+ ;;
++ powerpc-*-morphos*)
++ #targ_defvec=powerpc_elf32_vec
++ #targ_selvecs="powerpc_elf32_vec"
++ targ_defvec=powerpc_elf32_morphos_vec
++ targ_selvecs=powerpc_elf32_morphos_vec
++ ;;
+
+ #ifdef BFD64
+ riscvbe-*-* | riscv32be*-*-*)
+diff -ruN binutils-2.45/bfd/configure binutils-2.45_mos/bfd/configure
+--- binutils-2.45/bfd/configure 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/configure 2025-07-27 14:39:08.700060484 +0300
+@@ -15473,6 +15473,8 @@
+ coff="cofflink.lo $coffgen"
+ ecoff="ecofflink.lo $coffgen"
+ xcoff="xcofflink.lo $coffgen"
++elf_morphos="elf.lo elflink.lo elf-attrs.lo elf-strtab.lo elf-properties.lo
++ elf-eh-frame.lo dwarf1.lo dwarf2.lo"
+
+ elfxx_x86="elfxx-x86.lo elf-ifunc.lo elf-vxworks.lo"
+ for vec in $selvecs
+@@ -15656,6 +15658,7 @@
+ powerpc_boot_vec) tb="$tb ppcboot.lo" ;;
+ powerpc_elf32_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;;
+ powerpc_elf32_le_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;;
++ powerpc_elf32_morphos_vec) tb="$tb elf32-ppc.lo elf32.lo $elf_morphos elf-vxworks.lo";;
+ powerpc_elf32_fbsd_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;;
+ powerpc_elf32_vxworks_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;;
+ powerpc_elf64_vec) tb="$tb elf64-ppc.lo elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
+diff -ruN binutils-2.45/bfd/configure.host binutils-2.45_mos/bfd/configure.host
+--- binutils-2.45/bfd/configure.host 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/configure.host 2025-07-27 14:39:08.712060584 +0300
+@@ -97,4 +97,6 @@
+ ac_cv_header_sys_time_h=no
+ ac_cv_header_unistd_h=no
+ ;;
++
++powerpc-*-morphos*) HDEFINES="-D_LARGEFILE64_SOURCE" ;;
+ esac
+diff -ruN binutils-2.45/bfd/elf32-ppc.c binutils-2.45_mos/bfd/elf32-ppc.c
+--- binutils-2.45/bfd/elf32-ppc.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/elf32-ppc.c 2025-07-27 14:39:08.704060517 +0300
+@@ -53,6 +53,11 @@
+ static bfd_reloc_status_type ppc_elf_unhandled_reloc
+ (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **);
+
++#ifdef MORPHOS_TARGET
++int ddr_count;
++bfd_byte *ddr_ptr;
++#endif
++
+ /* Branch prediction bit for branch taken relocs. */
+ #define BRANCH_PREDICT_BIT 0x200000
+ /* Mask to set RA in memory instructions. */
+@@ -693,6 +698,25 @@
+ /* Phony reloc to handle AIX style TOC entries. */
+ HOW (R_PPC_TOC16, 2, 16, 0xffff, 0, false, signed,
+ ppc_elf_unhandled_reloc),
++
++#ifdef MORPHOS_TARGET
++ /* 32-bit relocation relative to _SDA_BASE_ */
++ HOW (R_PPC_MORPHOS_DREL, 4, 32, 0, 0, false, bitfield,
++ bfd_elf_generic_reloc),
++
++ /* Lower 16 bits of a relocation relative to _SDA_BASE */
++ HOW (R_PPC_MORPHOS_DREL_LO, 2, 16, 0xffff, 0, false, dont,
++ bfd_elf_generic_reloc),
++
++ /* Upper 16 bits of a relocation relative to _SDA_BASE */
++ HOW (R_PPC_MORPHOS_DREL_HI, 2, 16, 0xffff, 16, false, dont,
++ bfd_elf_generic_reloc),
++
++ /* Upper 16 bits of a relocation relative to _SDA_BASE */
++ HOW (R_PPC_MORPHOS_DREL_HA, 2, 16, 0xffff, 16, false, dont,
++ bfd_elf_generic_reloc),
++#endif
++
+ };
+
+ /* Initialize the ppc_elf_howto_table, so that linear accesses can be done. */
+@@ -859,6 +883,14 @@
+ case BFD_RELOC_PPC_REL16DX_HA: r = R_PPC_REL16DX_HA; break;
+ case BFD_RELOC_VTABLE_INHERIT: r = R_PPC_GNU_VTINHERIT; break;
+ case BFD_RELOC_VTABLE_ENTRY: r = R_PPC_GNU_VTENTRY; break;
++
++#ifdef MORPHOS_TARGET
++ /* Special MorphOS relocs. */
++ case BFD_RELOC_PPC_MORPHOS_DREL: r = R_PPC_MORPHOS_DREL; break;
++ case BFD_RELOC_PPC_MORPHOS_DREL_LO: r = R_PPC_MORPHOS_DREL_LO; break;
++ case BFD_RELOC_PPC_MORPHOS_DREL_HI: r = R_PPC_MORPHOS_DREL_HI; break;
++ case BFD_RELOC_PPC_MORPHOS_DREL_HA: r = R_PPC_MORPHOS_DREL_HA; break;
++#endif
+ }
+
+ return ppc_elf_howto_table[r];
+@@ -922,6 +954,31 @@
+
+ /* Handle the R_PPC_ADDR16_HA and R_PPC_REL16_HA relocs. */
+
++#ifdef MORPHOS_TARGET
++static bfd_reloc_status_type
++ppc_elf_addr16_ha_reloc (bfd *abfd ATTRIBUTE_UNUSED,
++ arelent *r,
++ asymbol *symbol ATTRIBUTE_UNUSED,
++ void *data ATTRIBUTE_UNUSED,
++ asection *sec,
++ bfd *output_bfd,
++ char **error_message ATTRIBUTE_UNUSED)
++{
++
++ /*bfd_vma relocation;*/
++ if (output_bfd != NULL)
++ {
++ r->address += sec->output_offset;
++ return bfd_reloc_ok;
++ }
++ else
++ {
++ r->address += sec->output_offset;
++ sec->output_section->orelocation[sec->output_section->reloc_count++]=r;
++ return bfd_reloc_ok;
++ }
++}
++#else
+ static bfd_reloc_status_type
+ ppc_elf_addr16_ha_reloc (bfd *abfd,
+ arelent *reloc_entry,
+@@ -969,6 +1026,7 @@
+ bfd_put_32 (abfd, insn, (bfd_byte *) data + octets);
+ return bfd_reloc_ok;
+ }
++#endif
+
+ static bfd_reloc_status_type
+ ppc_elf_unhandled_reloc (bfd *abfd,
+@@ -3415,6 +3473,15 @@
+ return false;
+ break;
+ }
++#ifdef MORPHOS_TARGET
++ #warning "Morphos: what to do here?"
++ case R_PPC_MORPHOS_DREL:
++ case R_PPC_MORPHOS_DREL_LO:
++ case R_PPC_MORPHOS_DREL_HI:
++ case R_PPC_MORPHOS_DREL_HA:
++ //printf("MorphOS: What to do here?\n");
++ break;
++#endif
+
+ dodyn:
+ /* Set up information for symbols that might need dynamic
+@@ -5070,18 +5137,17 @@
+ return need;
+ }
+
+-/* If H is undefined, make it dynamic if that makes sense. */
++/* If H is undefined weak, make it dynamic if that makes sense. */
+
+ static bool
+-ensure_undef_dynamic (struct bfd_link_info *info,
+- struct elf_link_hash_entry *h)
++ensure_undefweak_dynamic (struct bfd_link_info *info,
++ struct elf_link_hash_entry *h)
+ {
+ struct elf_link_hash_table *htab = elf_hash_table (info);
+
+ if (htab->dynamic_sections_created
+- && ((info->dynamic_undefined_weak != 0
+- && h->root.type == bfd_link_hash_undefweak)
+- || h->root.type == bfd_link_hash_undefined)
++ && info->dynamic_undefined_weak != 0
++ && h->root.type == bfd_link_hash_undefweak
+ && h->dynindx == -1
+ && !h->forced_local
+ && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
+@@ -5124,8 +5190,9 @@
+ && eh->has_addr16_lo
+ && htab->params->pic_fixup > 0))
+ {
+- /* Make sure this symbol is output as a dynamic symbol. */
+- if (!ensure_undef_dynamic (info, &eh->elf))
++ /* Make sure this symbol is output as a dynamic symbol.
++ Undefined weak syms won't yet be marked as dynamic. */
++ if (!ensure_undefweak_dynamic (info, &eh->elf))
+ return false;
+
+ unsigned int need = got_entries_needed (eh->tls_mask);
+@@ -5232,8 +5299,9 @@
+
+ if (h->dyn_relocs != NULL)
+ {
+- /* Make sure this symbol is output as a dynamic symbol. */
+- if (!ensure_undef_dynamic (info, h))
++ /* Make sure undefined weak symbols are output as a dynamic
++ symbol in PIEs. */
++ if (!ensure_undefweak_dynamic (info, h))
+ return false;
+ }
+ }
+@@ -5254,8 +5322,9 @@
+ && eh->has_addr16_lo
+ && htab->params->pic_fixup > 0))
+ {
+- /* Make sure this symbol is output as a dynamic symbol. */
+- if (!ensure_undef_dynamic (info, h))
++ /* Make sure this symbol is output as a dynamic symbol.
++ Undefined weak syms won't yet be marked as dynamic. */
++ if (!ensure_undefweak_dynamic (info, h))
+ return false;
+
+ if (h->dynindx == -1)
+@@ -5301,7 +5370,7 @@
+ asection *s;
+ bool dyn;
+
+- if (!ensure_undef_dynamic (info, h))
++ if (!ensure_undefweak_dynamic (info, h))
+ return false;
+
+ dyn = !use_local_plt (info, h);
+@@ -6948,6 +7017,66 @@
+ return swap_reloc_out (obfd, rel, loc, s);
+ }
+
++#ifdef MORPHOS_TARGET
++static void morphos_copy_reloc(bfd *output_bfd, asection *input_section, asection *sec, enum elf_ppc_reloc_type r_type, bfd_vma relocation, bfd_vma addend, bfd_vma offset2)
++{
++ Elf_Internal_Rela outrel2;
++ Elf_Internal_Shdr *rel_hdr = _bfd_elf_single_rel_hdr(input_section->output_section);
++ bool skip;
++
++ skip = false;
++
++ if(sec == NULL) /* Don't know if it is possible... */
++ return;
++
++ /*printf("copying reloc %d, addend=%x, rel=%x, indx=%d, offset=%x, sec_vma=%x, sh_size=%d, count=%d, rsize=%ld\n",
++ r_type,(int)addend,(int)relocation,sec->output_section->target_index,
++ (int)sec->output_offset,(int)sec->output_section->vma, (unsigned int)rel_hdr->sh_size, input_section->output_section->reloc_count,
++ sizeof(Elf_Internal_Rela));*/
++
++ if(input_section->sec_info_type == SEC_INFO_TYPE_STABS)
++ {
++ bfd_vma off;
++
++ off = _bfd_stab_section_offset(input_section, elf_section_data(input_section)->sec_info,
++ offset2);
++
++ if(off == (bfd_vma) - 1)
++ skip = true;
++
++ outrel2.r_offset = off;
++ }
++ else
++ {
++ outrel2.r_offset = offset2;
++ }
++
++
++ outrel2.r_info = ELF32_R_INFO(sec->output_section->target_index, r_type);
++ outrel2.r_addend = relocation + addend - sec->output_section->vma;
++ outrel2.r_offset += input_section->output_offset;
++
++ if((input_section->output_section->reloc_count * sizeof(Elf32_External_Rela)) >= (unsigned int)rel_hdr->sh_size)
++ {
++ printf("skipping reloc (out of space)\n");
++ }
++ else
++ {
++ if(skip)
++ {
++ memset(&outrel2, 0, sizeof outrel2);
++ }
++ else
++ {
++ bfd_elf32_swap_reloca_out(output_bfd, &outrel2,
++ (bfd_byte*)((Elf32_External_Rela *)rel_hdr->contents
++ + input_section->output_section->reloc_count));
++ ++input_section->output_section->reloc_count;
++ }
++ }
++}
++#endif
++
+ /* The RELOCATE_SECTION function is called by the ELF backend linker
+ to handle the relocations for a section.
+
+@@ -6998,9 +7127,15 @@
+ bfd_vma *local_got_offsets;
+ bool ret = true;
+ bfd_vma d_offset = (bfd_big_endian (input_bfd) ? 2 : 0);
++#ifndef MORPHOS_TARGET
+ bool is_vxworks_tls;
++#endif
+ unsigned int picfixup_size = 0;
+ struct ppc_elf_relax_info *relax_info = NULL;
++#ifdef MORPHOS_TARGET
++ asection *sdata_sec = NULL;
++ asection *sbss_sec = NULL;
++#endif
+
+ #ifdef DEBUG
+ _bfd_error_handler ("ppc_elf_relocate_section called for %pB section %pA, "
+@@ -7022,15 +7157,26 @@
+ if (!ppc_elf_howto_table[R_PPC_ADDR32])
+ ppc_elf_howto_init ();
+
++#ifdef MORPHOS_TARGET
++ sdata_sec = bfd_get_section_by_name(output_bfd, ".sdata");
++ if (sdata_sec)
++ sdata_sec = sdata_sec->output_section;
++ sbss_sec = bfd_get_section_by_name(output_bfd, ".sbss");
++ if (sbss_sec)
++ sbss_sec = sbss_sec->output_section;
++#endif
++
+ htab = ppc_elf_hash_table (info);
+ local_got_offsets = elf_local_got_offsets (input_bfd);
+ symtab_hdr = &elf_symtab_hdr (input_bfd);
+ sym_hashes = elf_sym_hashes (input_bfd);
+ /* We have to handle relocations in vxworks .tls_vars sections
+ specially, because the dynamic loader is 'weird'. */
++#ifndef MORPHOS_TARGET
+ is_vxworks_tls = (htab->elf.target_os == is_vxworks && bfd_link_pic (info)
+ && !strcmp (input_section->output_section->name,
+ ".tls_vars"));
++#endif
+ if (input_section->sec_info_type == SEC_INFO_TYPE_TARGET)
+ relax_info = elf_section_data (input_section)->sec_info;
+ rel = wrel = relocs;
+@@ -7044,6 +7190,10 @@
+ asection *sec;
+ struct elf_link_hash_entry *h;
+ const char *sym_name;
++#ifdef MORPHOS_TARGET
++ bool copy = false;
++ bfd_vma offset2 = rel->r_offset;
++#endif
+ reloc_howto_type *howto;
+ unsigned long r_symndx;
+ bfd_vma relocation;
+@@ -8084,9 +8234,11 @@
+ /* fall through */
+
+ dodyn:
++#ifndef MORPHOS_TARGET
+ if ((input_section->flags & SEC_ALLOC) == 0
+ || is_vxworks_tls)
+ break;
++#endif
+
+ if (bfd_link_pic (info)
+ ? ((h == NULL
+@@ -8243,6 +8395,107 @@
+ break;
+ }
+ }
++#ifdef MORPHOS_TARGET
++ else if (r_type == R_PPC_REL24 || r_type == R_PPC_REL14)
++ {
++ if (sec->output_section != input_section->output_section)
++ {
++ (*_bfd_error_handler) ("%s: The target (%s) of a %s relocation is in the wrong section (%pA)",
++ bfd_get_filename (input_bfd),
++ sym_name,
++ ppc_elf_howto_table[ (int)r_type ]->name,
++ input_section);
++
++ bfd_set_error (bfd_error_bad_value);
++ ret = false;
++ continue;
++ }
++ break;
++ }
++ else if (r_type == R_PPC_REL32)
++ {
++ if (sec->output_section != input_section->output_section)
++ copy = true;
++ else
++ break;
++ }
++ else if (ddr_ptr && sec && r_type == R_PPC_ADDR32 &&
++ (sec->output_section == sdata_sec ||
++ sec->output_section == sbss_sec /*||
++ !strcmp(bfd_get_section_name(abfd, sec), "COMMON") ||
++ !strcmp(bfd_get_section_name(abfd, sec), ".data") ||
++ !strcmp(bfd_get_section_name(abfd, sec), ".bss")*/) &&
++ (input_section->output_section == sdata_sec ||
++ input_section->output_section == sbss_sec /*||
++ !strcmp(bfd_get_section_name(abfd, input_section), "COMMON") ||
++ !strcmp(bfd_get_section_name(abfd, input_section), ".data") ||
++ !strcmp(bfd_get_section_name(abfd, input_section), ".bss")*/))
++ {
++ int tmp = input_section->output_offset + offset2;
++ ++ddr_count;
++ ddr_ptr[0] = (bfd_byte)(tmp >> 24);
++ ddr_ptr[1] = (bfd_byte)(tmp >> 16);
++ ddr_ptr[2] = (bfd_byte)(tmp >> 8);
++ ddr_ptr[3] = (bfd_byte)tmp;
++ ddr_ptr += 4;
++ copy = true;
++/*if (sec->output_section != sdata_sec && sec->output_section != sbss_sec)
++{
++ if (sdata_sec)
++ printf("sdata %p output %p ", sdata_sec, sdata_sec->output_section);
++ if (sbss_sec)
++ printf("sbss %p output %p ", sbss_sec, sbss_sec->output_section);
++ printf("*** sec %p output %p <%s> <%s>\n", sec, sec->output_section,
++ bfd_get_section_name(abfd, sec), bfd_get_section_name(abfd, input_section));
++}*/
++ break;
++ }
++ else if (sec && !bfd_is_abs_section(sec))
++ {
++ copy = true;
++ break;
++ }
++
++ if (copy && ddr_ptr && sec &&
++ strcmp(input_section->name, "lnkdata") &&
++ (sec->output_section == sdata_sec ||
++ sec->output_section == sbss_sec ||
++ !strcmp(sec->name, "COMMON") ||
++ !strcmp(sec->name, ".data") ||
++ !strcmp(sec->name, ".bss") ||
++ !strncmp(sec->name, ".gnu.linkonce.s.", 16) ||
++ !strncmp(sec->name, ".gnu.linkonce.b.", 16) ||
++ !strncmp(sec->name, ".gnu.linkonce.sb.", 17))
++ /*&&
++ (r_type != R_PPC_ADDR32 ||
++ !(input_section->output_section == sdata_sec->output_section ||
++ input_section->output_section == sbss_sec->output_section ||
++ !strcmp(bfd_get_section_name(abfd, input_section), "COMMON") ||
++ !strcmp(bfd_get_section_name(abfd, input_section), ".data") ||
++ !strcmp(bfd_get_section_name(abfd, input_section), ".bss")))*/)
++ {
++ (*_bfd_error_handler) ("%s: The target (%s) of a %s relocation is in the wrong section (%s)",
++ bfd_get_filename (input_bfd),
++ sym_name,
++ ppc_elf_howto_table[ (int)r_type ]->name,
++ sec->name);
++ bfd_set_error (bfd_error_bad_value);
++ ret = false;
++ continue;
++ }
++
++ /* Arithmetic adjust relocations that aren't going into a
++ shared object. */
++ if (r_type == R_PPC_ADDR16_HA
++ /* It's just possible that this symbol is a weak symbol
++ that's not actually defined anywhere. In that case,
++ 'sec' would be NULL, and we should leave the symbol
++ alone (it will be set to zero elsewhere in the link). */
++ && sec != NULL)
++ {
++ addend += ((relocation + addend) & 0x8000) << 1;
++ }
++#endif
+ break;
+
+ case R_PPC_RELAX_PLT:
+@@ -8306,12 +8559,16 @@
+
+ /* First insn is HA, second is LO. */
+ insn = *stub++;
++#ifndef MORPHOS_TARGET
+ insn |= ((relocation + 0x8000) >> 16) & 0xffff;
++#endif
+ bfd_put_32 (input_bfd, insn, contents + insn_offset);
+ insn_offset += 4;
+
+ insn = *stub++;
++#ifndef MORPHOS_TARGET
+ insn |= relocation & 0xffff;
++#endif
+ bfd_put_32 (input_bfd, insn, contents + insn_offset);
+ insn_offset += 4;
+ size -= 2;
+@@ -8331,10 +8588,21 @@
+ wrel->r_offset = rel->r_offset + d_offset;
+ wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_HA);
+ wrel->r_addend = rel->r_addend;
++
++#ifdef MORPHOS_TARGET
++ //printf("DEBUG: %s(%d)\n", __FUNCTION__, __LINE__);
++ morphos_copy_reloc(output_bfd, input_section, sec, R_PPC_ADDR16_HA, relocation, 0, offset2 + 2 + 0);
++#endif
++
+ memmove (wrel + 1, wrel, (relend - wrel - 1) * sizeof (*wrel));
+ wrel++, rel++;
+ wrel->r_offset += 4;
+ wrel->r_info = ELF32_R_INFO (r_symndx, R_PPC_ADDR16_LO);
++
++#ifdef MORPHOS_TARGET
++ //printf("DEBUG: %s(%d)\n", __FUNCTION__, __LINE__);
++ morphos_copy_reloc(output_bfd, input_section, sec, R_PPC_ADDR16_LO, relocation, 0, offset2 + 2 + 4);
++#endif
+ }
+ else
+ goto de_fault;
+@@ -8492,6 +8760,9 @@
+ }
+ addend -= SYM_VAL (sda);
+
++#ifdef MORPHOS_TARGET
++ addend += sda->root.u.def.section->output_offset;
++#endif
+ name = bfd_section_name (sec->output_section);
+ if (!(strcmp (name, ".sdata") == 0
+ || strcmp (name, ".sbss") == 0))
+@@ -8508,6 +8779,59 @@
+ }
+ break;
+
++#ifdef MORPHOS_TARGET
++ /* relocate against _SDA_BASE_, in large data mode */
++ case R_PPC_MORPHOS_DREL:
++ case R_PPC_MORPHOS_DREL_LO:
++ case R_PPC_MORPHOS_DREL_HI:
++ case R_PPC_MORPHOS_DREL_HA:
++ {
++ const char *name;
++
++ if (sec == NULL
++ || sec->output_section == NULL
++ || !is_static_defined (htab->sdata[0].sym))
++ {
++ unresolved_reloc = true;
++ break;
++ }
++ name = bfd_section_name (sec->output_section);
++ if(strcmp(name, ".sdata") != 0
++ && strcmp(name, ".sbss") != 0
++ && strcmp(name, ".data") != 0
++ && strcmp(name, ".bss") != 0
++ && strncmp(name, ".ctors", 6) != 0
++ && strncmp(name, ".dtors", 6) != 0)
++ {
++
++ //info->callbacks->einfo
++ _bfd_error_handler
++ /* xgettext:c-format */
++ (_("%pB: the target (%s) of a %s relocation is "
++ "in the wrong output section (%s)\n"),
++ input_bfd,
++ sym_name,
++ howto->name,
++ name);
++ }
++ else
++ {
++ /*printf("%s: addend = %x, sdata->val = %x, vma = %x, output_offset = %x\n",
++ howto->name,
++ addend, htab->sdata[0].sym->root.u.def.value,
++ htab->sdata[0].sym->root.u.def.section->output_section->vma,
++ htab->sdata[0].sym->root.u.def.section->output_offset);*/
++
++ addend -= (htab->sdata[0].sym->root.u.def.value
++ + htab->sdata[0].sym->root.u.def.section->output_section->vma);
++ if(r_type == R_PPC_MORPHOS_DREL_HA)
++ addend += ((relocation + addend) & 0x8000) << 1;
++ }
++ break;
++
++ }
++#endif
++
+ /* Relocate against _SDA2_BASE_. */
+ case R_PPC_EMB_SDA2REL:
+ {
+@@ -8967,7 +9291,12 @@
+ case R_PPC_GOT_DTPREL16_HA:
+ /* Add 0x10000 if sign bit in 0:15 is set.
+ Bits 0:15 are not used. */
+- addend += 0x8000;
++#ifdef MORPHOS_TARGET
++ if(r_type != R_PPC_ADDR16_HA) /* fm: MorphOS needs addend at 0 ... */
++#endif
++ {
++ addend += 0x8000;
++ }
+ break;
+
+ case R_PPC_ADDR16:
+@@ -9034,6 +9363,7 @@
+ (long) addend);
+ #endif
+
++#ifndef MORPHOS_TARGET //NB
+ if (unresolved_reloc
+ && !((input_section->flags & SEC_DEBUGGING) != 0
+ && h->def_dynamic)
+@@ -9048,6 +9378,7 @@
+ sym_name);
+ ret = false;
+ }
++#endif
+
+ /* 16-bit fields in insns mostly have signed values, but a
+ few insns have 16-bit unsigned values. Really, we should
+@@ -9078,7 +9409,68 @@
+ howto = &alt_howto;
+ }
+ }
++#ifdef MORPHOS_TARGET
++ if (copy)
++ {
++ //printf("DEBUG: %s(%d)\n", __FUNCTION__, __LINE__);
++ morphos_copy_reloc(output_bfd, input_section, sec, r_type, relocation, addend, offset2);
++ }
++ else
++ {
++ /*printf("applying reloc %d, sym=%s addend=%x, rel=%x, indx=%d, offset=%x, sec_vma=%x\n",
++ r_type,sym_name,addend,relocation,sec->output_section->target_index,
++ sec->output_offset,sec->output_section->vma);*/
++ r = _bfd_final_link_relocate (howto,
++ input_bfd,
++ input_section,
++ contents,
++ offset2,
++ relocation,
++ addend);
+
++report_reloc:
++ if (r != bfd_reloc_ok)
++ {
++ ret = false;
++ if (r == bfd_reloc_overflow)
++ {
++ const char *name;
++ if (h != NULL)
++ name = h->root.root.string;
++ else
++ {
++ name = bfd_elf_string_from_elf_section (input_bfd,
++ symtab_hdr->sh_link,
++ sym->st_name);
++ if (name == NULL)
++ break;
++
++ if (*name == '\0')
++ name = bfd_section_name (sec);
++ }
++
++ (*info->callbacks->reloc_overflow) (info,
++ (h ? &h->root : NULL),
++ sym_name,
++ howto->name,
++ rel->r_addend,
++ input_bfd,
++ input_section,
++ rel->r_offset);
++ }
++ else
++ {
++ info->callbacks->einfo
++ /* xgettext:c-format */
++ (_("%H: %s reloc against `%s': error %d\n"),
++ input_bfd, input_section, rel->r_offset,
++ howto->name, sym_name, (int) r);
++ ret = false;
++ }
++ }
++ }
++
++#else
+ if (r_type == R_PPC_REL16DX_HA)
+ {
+ /* Split field reloc isn't handled by _bfd_final_link_relocate. */
+@@ -9130,6 +9522,7 @@
+ ret = false;
+ }
+ }
++#endif
+ copy_reloc:
+ if (wrel != rel)
+ *wrel = *rel;
+@@ -10377,11 +10770,13 @@
+
+ return ret;
+ }
+-
++
++#ifdef MORPHOS_TARGET
++
+ #define TARGET_LITTLE_SYM powerpc_elf32_le_vec
+ #define TARGET_LITTLE_NAME "elf32-powerpcle"
+-#define TARGET_BIG_SYM powerpc_elf32_vec
+-#define TARGET_BIG_NAME "elf32-powerpc"
++#define TARGET_BIG_SYM powerpc_elf32_morphos_vec
++#define TARGET_BIG_NAME "elf32-morphos"
+ #define ELF_ARCH bfd_arch_powerpc
+ #define ELF_TARGET_ID PPC32_ELF_DATA
+ #define ELF_MACHINE_CODE EM_PPC
+@@ -10404,6 +10799,8 @@
+ #define elf_backend_rela_normal 1
+ #define elf_backend_caches_rawsize 1
+
++#define elf_backend_got_symbol_offset 4
++
+ #define bfd_elf32_mkobject ppc_elf_mkobject
+ #define bfd_elf32_bfd_merge_private_bfd_data ppc_elf_merge_private_bfd_data
+ #define bfd_elf32_bfd_relax_section ppc_elf_relax_section
+@@ -10443,8 +10840,11 @@
+ #define elf_backend_init_index_section _bfd_elf_init_1_index_section
+ #define elf_backend_lookup_section_flags_hook ppc_elf_lookup_section_flags
+
++
+ #include "elf32-target.h"
+
++#else
++
+ /* FreeBSD Target */
+
+ #undef TARGET_LITTLE_SYM
+@@ -10577,3 +10977,4 @@
+ #define elf32_bed ppc_elf_vxworks_bed
+
+ #include "elf32-target.h"
++#endif //MORPHOS_TARGET
+diff -ruN binutils-2.45/bfd/elf.c binutils-2.45_mos/bfd/elf.c
+--- binutils-2.45/bfd/elf.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/elf.c 2025-07-27 14:39:08.704060517 +0300
+@@ -7052,8 +7052,12 @@
+
+ /* Assign file positions for all the reloc sections which are not part
+ of the loadable file image, and the file position of section headers. */
+-
+-static bool
++#ifdef MORPHOS_TARGET
++bool _bfd_elf_assign_file_positions_for_non_load (bfd *abfd);
++#else
++static
++#endif
++bool
+ _bfd_elf_assign_file_positions_for_non_load (bfd *abfd)
+ {
+ file_ptr off;
+diff -ruN binutils-2.45/bfd/elflink.c binutils-2.45_mos/bfd/elflink.c
+--- binutils-2.45/bfd/elflink.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/elflink.c 2025-08-24 04:52:57.719225910 +0300
+@@ -37,6 +37,9 @@
+ #define CHAR_BIT 8
+ #endif
+
++extern int ddr_count;
++extern bfd_byte *ddr_ptr;
++
+ /* This struct is used to pass information to routines called via
+ elf_link_hash_traverse which must return failure. */
+
+@@ -9761,6 +9764,12 @@
+ unsigned int count = reldata->count;
+ struct elf_link_hash_entry **rel_hash = reldata->hashes;
+
++
++#ifdef MORPHOS_TARGET
++ if (!(sort && count != 0))
++ reldata->hdr->sh_size = sec->reloc_count * reldata->hdr->sh_entsize;
++#endif
++
+ if (reldata->hdr->sh_entsize == bed->s->sizeof_rel)
+ {
+ swap_in = bed->s->swap_reloc_in;
+@@ -10921,7 +10930,9 @@
+ sym.st_value = h->root.u.def.value + input_sec->output_offset;
+ if (!bfd_link_relocatable (flinfo->info))
+ {
++#ifndef MORPHOS_TARGET
+ sym.st_value += input_sec->output_section->vma;
++#endif
+ if (h->type == STT_TLS)
+ {
+ asection *tls_sec = elf_hash_table (flinfo->info)->tls_sec;
+@@ -11581,7 +11592,9 @@
+ osym.st_value += isec->output_offset;
+ if (!bfd_link_relocatable (flinfo->info))
+ {
++#ifndef MORPHOS_TARGET
+ osym.st_value += isec->output_section->vma;
++#endif
+ if (ELF_ST_TYPE (osym.st_info) == STT_TLS)
+ {
+ /* STT_TLS symbols are relative to PT_TLS segment base. */
+@@ -11963,7 +11976,9 @@
+ rel_hash_list = rel_hash;
+ rela_hash_list = NULL;
+ last_offset = o->output_offset;
+- if (!bfd_link_relocatable (flinfo->info))
++#ifndef MORPHOS_TARGET
++ if (!bfd_link_relocatable (flinfo->info))
++#endif
+ last_offset += o->output_section->vma;
+ for (next_erel = 0; irela < irelaend; irela++, next_erel++)
+ {
+@@ -12003,7 +12018,9 @@
+ irela->r_offset += o->output_offset;
+
+ /* Relocs in an executable have to be virtual addresses. */
++#ifndef MORPHOS_TARGET
+ if (!bfd_link_relocatable (flinfo->info))
++#endif
+ irela->r_offset += o->output_section->vma;
+
+ last_offset = irela->r_offset;
+@@ -12132,7 +12149,9 @@
+ sym.st_value += sec->output_offset;
+ if (!bfd_link_relocatable (flinfo->info))
+ {
++#ifndef MORPHOS_TARGET
+ sym.st_value += osec->vma;
++#endif
+ if (ELF_ST_TYPE (sym.st_info) == STT_TLS)
+ {
+ struct elf_link_hash_table *htab
+@@ -12631,6 +12650,12 @@
+ Elf_Internal_Shdr *symtab_shndx_hdr;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ struct elf_outext_info eoinfo;
++#ifdef MORPHOS_TARGET
++ bfd_size_type max_datadata_reloc_count;
++ asection *ddr_sec;
++ asection *sdata_sec = NULL;
++ asection *sbss_sec = NULL;
++#endif
+ bool merged;
+ size_t relativecount;
+ size_t relr_entsize;
+@@ -12645,11 +12670,54 @@
+ if (bfd_link_pic (info))
+ abfd->flags |= DYNAMIC;
+
++#ifdef MORPHOS_TARGET
++#if 0 // Disabled for now - #ifdef MORPHOS_SDK_RELEASE_ID
++if (bfd_link_executable (info) && bfd_get_flavour (abfd) == bfd_target_elf_flavour)
++{
++ /* If .comment section is missing, add one with the SDK ID. Note: This
++ later needs to be adjusted to modify existing section on the fly,
++ replacing the hack elsewhere.. For now we just add this as backup to
++ fix "ld -b binary file -o file.o" usecase.. - Piru */
++ asection *s = bfd_get_section_by_name( abfd, ".comment" );
++ if (s == NULL)
++ {
++ flagword flags = (SEC_MERGE | SEC_STRINGS | SEC_HAS_CONTENTS | SEC_READONLY);
++ s = bfd_make_section_with_flags (abfd, ".comment", flags);
++ if (s != NULL && bfd_set_section_alignment (s, 0))
++ {
++ struct bfd_link_order *link_order;
++#define xstr_(s) str_(s)
++#define str_(s) #s
++ static char data[] = "\0MorphOS_SDK: " xstr_(MORPHOS_SDK_RELEASE_ID);
++ elf_section_type (s) = SHT_PROGBITS;
++ s->size = sizeof (data);
++ s->output_section = s;
++ s->output_offset = 0;
++ link_order = bfd_new_link_order (abfd, s);
++ if (link_order)
++ {
++ link_order->type = bfd_data_link_order;
++ link_order->u.data.contents = (unsigned char *) data;
++ link_order->u.data.size = s->size;
++ link_order->size = s->size;
++ link_order->offset = 0;
++ }
++ }
++ }
++}
++#endif
++ bfd_set_start_address(abfd, 0);
++#endif
++
+ dynamic = htab->dynamic_sections_created;
+ dynobj = htab->dynobj;
+
++#ifdef MORPHOS_TARGET
++ emit_relocs = 1;
++#else
+ emit_relocs = (bfd_link_relocatable (info)
+ || info->emitrelocations);
++#endif
+
+ memset (&flinfo, 0, sizeof (flinfo));
+ flinfo.info = info;
+@@ -12730,6 +12798,10 @@
+ if (sections_removed)
+ _bfd_fix_excluded_sec_syms (abfd, info);
+
++#ifdef MORPHOS_TARGET
++ ddr_sec = bfd_get_section_by_name(abfd, "ddrelocs");
++#endif
++
+ /* Count up the number of relocations we will output for each output
+ section, so that we know the sizes of the reloc sections. We
+ also figure out some maximum sizes. */
+@@ -12755,6 +12827,9 @@
+ max_sym_count = 0;
+ max_sym_shndx_count = 0;
+ merged = false;
++#ifdef MORPHOS_TARGET
++ max_datadata_reloc_count = 0;
++#endif
+ for (o = abfd->sections; o != NULL; o = o->next)
+ {
+ struct bfd_elf_section_data *esdo = elf_section_data (o);
+@@ -12890,8 +12965,24 @@
+ }
+ }
+
++#ifdef MORPHOS_TARGET
++ if (!strcmp(bfd_section_name(o), ".sdata"))
++ sdata_sec = o;
++ else if(!strcmp(bfd_section_name(o), ".sbss"))
++ sbss_sec = o;
++ else
++ bfd_set_section_vma(o, 0);
++
++ if (o->reloc_count > 0)
++ {
++ o->flags |= SEC_RELOC;
++ if (o == sdata_sec || o == sbss_sec)
++ max_datadata_reloc_count += o->reloc_count;
++ }
++#else
+ if (o->reloc_count > 0)
+ o->flags |= SEC_RELOC;
++#endif
+ else
+ {
+ /* Explicitly clear the SEC_RELOC flag. The linker tends to
+@@ -12912,10 +13003,44 @@
+ if (! bfd_link_relocatable (info) && merged)
+ elf_link_hash_traverse (htab, _bfd_elf_link_sec_merge_syms, abfd);
+
++#ifdef MORPHOS_TARGET
++ if (sdata_sec)
++ {
++ if (sbss_sec)
++ {
++ /* Emm: all this is pretty hackish and I'm not sure it's 100% safe. There is probably
++ * a better place to do that too.
++ */
++ int align1 = bfd_section_alignment (sdata_sec);
++ int align = bfd_section_alignment (sbss_sec);
++
++ int mask = (1 << align) - 1;
++//printf("align1 %d align %d\n", align1, align);
++ if (align > align1)
++ bfd_set_section_alignment(sdata_sec, align);
++//printf("data_size 0x%x\n", (unsigned int)(sbss_sec->vma - sdata_sec->vma));
++//printf("-> 0x%x\n", (unsigned int)(sbss_sec->vma - sdata_sec->vma + mask) & ~mask);
++//printf("section_size : 0x%x\n",(unsigned int)sdata_sec->rawsize);
++ sdata_sec->rawsize = (sdata_sec->rawsize + mask) & ~mask;
++//printf("section_size : 0x%x\n",(unsigned int)sdata_sec->rawsize);
++ //bfd_set_section_vma(abfd, sbss_sec, (sbss_sec->vma - sdata_sec->vma + mask) & ~mask);
++ bfd_set_section_vma(sbss_sec, sdata_sec->rawsize);
++ //sdata_sec->rawsize = sbss_sec->vma;
++//printf("section_size : 0x%x\n",(unsigned int)sdata_sec->rawsize);
++ }
++ bfd_set_section_vma(sdata_sec, 0);
++ }
++#endif
++
+ /* Figure out the file positions for everything but the symbol table
+ and the relocs. We set symcount to force assign_section_numbers
+ to create a symbol table. */
++
++#ifdef MORPHOS_TARGET
++ abfd->symcount = 1;
++#else
+ abfd->symcount = info->strip != strip_all || emit_relocs;
++#endif
+ BFD_ASSERT (! abfd->output_has_begun);
+ if (! _bfd_elf_compute_section_file_positions (abfd, info))
+ goto error_return;
+@@ -12944,6 +13069,12 @@
+ esdo->rel.count = 0;
+ esdo->rela.count = 0;
+
++#ifdef MORPHOS_TARGET
++ /* Use the reloc_count field as an index when outputting the
++ relocs. */
++ o->reloc_count = 0;
++#endif
++
+ if ((esdo->this_hdr.sh_offset == (file_ptr) -1)
+ && !bfd_section_is_ctf (o))
+ {
+@@ -12988,7 +13119,9 @@
+ = (elf_numsections (abfd) > (SHN_LORESERVE & 0xFFFF)
+ ? (Elf_External_Sym_Shndx *) -1 : NULL);
+
++#ifndef MORPHOS_TARGET
+ if (info->strip != strip_all || emit_relocs)
++#endif
+ {
+ file_ptr off = elf_next_file_pos (abfd);
+
+@@ -13034,8 +13167,12 @@
+ {
+ o->target_index = bfd_get_symcount (abfd);
+ elfsym.st_shndx = i;
++#ifdef MORPHOS_TARGET
++ elfsym.st_value = 0;
++#else
+ if (!bfd_link_relocatable (info))
+ elfsym.st_value = o->vma;
++#endif
+ if (name_local_sections)
+ name = o->name;
+ if (elf_link_output_symstrtab (&flinfo, name, &elfsym, o,
+@@ -13149,6 +13286,22 @@
+ info->callbacks->fatal
+ (_("%P: %pB: failed to finish relative relocations\n"), abfd);
+
++#ifdef MORPHOS_TARGET
++ if (ddr_sec)
++ {
++ ddr_count = 0;
++ ddr_ptr = (bfd_byte *)bfd_alloc(abfd, 4 * max_datadata_reloc_count + 4);
++ if (ddr_ptr)
++ {
++ ddr_ptr += 4;
++ }
++ else
++ goto error_return;
++ }
++ else
++ ddr_ptr = NULL;
++#endif
++
+ /* Since ELF permits relocations to be against local symbols, we
+ must have the local symbols available when we do the relocations.
+ Since we would rather only read the local symbols once, and we
+@@ -13267,7 +13420,18 @@
+ (abfd, info, &flinfo, elf_link_output_symstrtab)))
+ goto error_return;
+ }
++#ifdef MORPHOS_TARGET
++ /* Set the vma of the sections to 0. We can't do that before, otherwise the
++ relocation doesn't work properly for .sbss. */
++ {
++ int n = elf_elfheader(abfd)->e_shnum;
++ int ij;
+
++ Elf_Internal_Shdr **hdr = elf_elfsections(abfd);
++ for (ij = 1; ij < n; ++ij, ++hdr)
++ (*hdr)->sh_addr = 0;
++ }
++#endif
+ /* That wrote out all the local symbols. Finish up the symbol table
+ with the global symbols. Even if we want to strip everything we
+ can, we still need to deal with those global symbols that got
+@@ -13394,13 +13558,44 @@
+ free (htab->strtab);
+ htab->strtab = NULL;
+
++#ifdef MORPHOS_TARGET
++{
++file_ptr off = 0;
++
++ /* Add the __datadata_relocs table. */
++ if (ddr_sec)
++ {
++ int tmp = ddr_count ? ddr_count : -1;
++
++ Elf_Internal_Shdr *hdr = elf_elfsections(abfd)[_bfd_elf_section_from_bfd_section(abfd, ddr_sec)];
++ off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
++
++ ddr_sec->size = ddr_sec->rawsize = hdr->sh_size = 4 * ddr_count + 4;
++ hdr->sh_addralign = 4;
++
++ off = _bfd_elf_assign_file_position_for_section (hdr, off, true, 0);
++ ddr_ptr -= (ddr_count + 1) * 4;
++ ddr_ptr[0] = (bfd_byte)(tmp >> 24);
++ ddr_ptr[1] = (bfd_byte)(tmp >> 16);
++ ddr_ptr[2] = (bfd_byte)(tmp >> 8);
++ ddr_ptr[3] = (bfd_byte)tmp;
++
++ bfd_set_section_contents(abfd, ddr_sec, ddr_ptr, 0, hdr->sh_size);
++ }
++#endif
++
+ /* Now we know the size of the symtab section. */
+ if (bfd_get_symcount (abfd) > 0)
+ {
+ /* Finish up and write out the symbol string table (.strtab)
+ section. */
+ Elf_Internal_Shdr *symstrtab_hdr = NULL;
++#ifndef MORPHOS_TARGET
+ file_ptr off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
++#else
++ if(!off)
++ off = symtab_hdr->sh_offset + symtab_hdr->sh_size;
++#endif
+
+ if (elf_symtab_shndx_list (abfd))
+ {
+@@ -13450,6 +13645,9 @@
+ info->out_implib_bfd);
+ goto error_return;
+ }
++#ifdef MORPHOS_TARGET
++}
++#endif
+
+ /* Adjust the relocs to have the correct symbol indices. */
+ for (o = abfd->sections; o != NULL; o = o->next)
+diff -ruN binutils-2.45/bfd/hosts/morphos.h binutils-2.45_mos/bfd/hosts/morphos.h
+--- binutils-2.45/bfd/hosts/morphos.h 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/bfd/hosts/morphos.h 2025-07-27 14:39:08.704060517 +0300
+@@ -0,0 +1,5 @@
++/* Host configuration for MorphOS */
++#ifndef hosts_morphos_h
++#define hosts_morphos_h
++#include "hosts/std-host.h"
++#endif /* hosts_morphos_h */
+diff -ruN binutils-2.45/bfd/libbfd.h binutils-2.45_mos/bfd/libbfd.h
+--- binutils-2.45/bfd/libbfd.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/libbfd.h 2025-07-27 14:39:08.704060517 +0300
+@@ -1559,6 +1559,10 @@
+ "BFD_RELOC_PPC_EMB_RELST_HA",
+ "BFD_RELOC_PPC_EMB_BIT_FLD",
+ "BFD_RELOC_PPC_EMB_RELSDA",
++ "BFD_RELOC_PPC_MORPHOS_DREL",
++ "BFD_RELOC_PPC_MORPHOS_DREL_LO",
++ "BFD_RELOC_PPC_MORPHOS_DREL_HI",
++ "BFD_RELOC_PPC_MORPHOS_DREL_HA",
+ "BFD_RELOC_PPC_VLE_REL8",
+ "BFD_RELOC_PPC_VLE_REL15",
+ "BFD_RELOC_PPC_VLE_REL24",
+diff -ruN binutils-2.45/bfd/opncls.c binutils-2.45_mos/bfd/opncls.c
+--- binutils-2.45/bfd/opncls.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/opncls.c 2025-07-27 14:39:08.704060517 +0300
+@@ -817,7 +817,10 @@
+ /* If the file was open for writing and is now executable,
+ make it so. */
+ if (abfd->direction == write_direction
+- && (abfd->flags & (EXEC_P | DYNAMIC)) != 0)
++#ifndef MORPHOS_TARGET
++ && (abfd->flags & (EXEC_P | DYNAMIC)) != 0
++#endif
++ )
+ {
+ struct stat buf;
+
+diff -ruN binutils-2.45/bfd/reloc.c binutils-2.45_mos/bfd/reloc.c
+--- binutils-2.45/bfd/reloc.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/reloc.c 2025-07-27 14:39:08.708060551 +0300
+@@ -2610,6 +2610,14 @@
+ ENUMX
+ BFD_RELOC_PPC_EMB_RELSDA
+ ENUMX
++ BFD_RELOC_PPC_MORPHOS_DREL
++ENUMX
++ BFD_RELOC_PPC_MORPHOS_DREL_LO
++ENUMX
++ BFD_RELOC_PPC_MORPHOS_DREL_HI
++ENUMX
++ BFD_RELOC_PPC_MORPHOS_DREL_HA
++ENUMX
+ BFD_RELOC_PPC_VLE_REL8
+ ENUMX
+ BFD_RELOC_PPC_VLE_REL15
+diff -ruN binutils-2.45/bfd/sysdep.h binutils-2.45_mos/bfd/sysdep.h
+--- binutils-2.45/bfd/sysdep.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/sysdep.h 2025-07-27 14:39:08.708060551 +0300
+@@ -29,6 +29,9 @@
+ #include "config.h"
+ #include <stdio.h>
+
++#if defined(MORPHOS_TARGET) && !defined(__off64_t_defined)
++typedef int64_t off64_t;
++#endif
+ #ifdef HAVE_SYS_TYPES_H
+ #include <sys/types.h>
+ #endif
+diff -ruN binutils-2.45/bfd/targets.c binutils-2.45_mos/bfd/targets.c
+--- binutils-2.45/bfd/targets.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/bfd/targets.c 2025-07-27 14:39:08.708060551 +0300
+@@ -847,6 +847,7 @@
+ extern const bfd_target powerpc_elf32_vec;
+ extern const bfd_target powerpc_elf32_le_vec;
+ extern const bfd_target powerpc_elf32_fbsd_vec;
++extern const bfd_target powerpc_elf32_morphos_vec;
+ extern const bfd_target powerpc_elf32_vxworks_vec;
+ extern const bfd_target powerpc_elf64_vec;
+ extern const bfd_target powerpc_elf64_le_vec;
+@@ -1234,6 +1235,7 @@
+ &powerpc_elf32_vec,
+ &powerpc_elf32_le_vec,
+ &powerpc_elf32_fbsd_vec,
++ &powerpc_elf32_morphos_vec,
+ &powerpc_elf32_vxworks_vec,
+ #ifdef BFD64
+ &powerpc_elf64_vec,
+diff -ruN binutils-2.45/binutils/objcopy.c binutils-2.45_mos/binutils/objcopy.c
+--- binutils-2.45/binutils/objcopy.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/binutils/objcopy.c 2025-07-27 14:39:08.708060551 +0300
+@@ -1550,7 +1550,9 @@
+ {
+ asymbol **from = isyms, **to = osyms;
+ long src_count = 0, dst_count = 0;
++#ifndef MORPHOS_TARGET
+ int relocatable = (abfd->flags & (EXEC_P | DYNAMIC)) == 0;
++#endif
+
+ for (; src_count < *symcount; src_count++)
+ {
+@@ -1565,6 +1567,13 @@
+
+ undefined = bfd_is_und_section (bfd_asymbol_section (sym));
+
++#ifdef MORPHOS_TARGET
++ if (strip_symbols == STRIP_ALL && undefined)
++ {
++ add_specific_symbol(strdup(name), keep_specific_htab); /* Is this really correct? - Piru */
++ }
++#endif
++
+ if (add_sym_list)
+ {
+ struct addsym_node *ptr;
+@@ -1659,7 +1668,11 @@
+ keep = true;
+ used_in_reloc = true;
+ }
++#ifdef MORPHOS_TARGET
++ else if (0 /* Don't keep globals just because our executables are also relocatable. */
++#else
+ else if (relocatable /* Relocatable file. */
++#endif
+ && ((flags & (BSF_GLOBAL | BSF_WEAK)) != 0
+ || bfd_is_com_section (bfd_asymbol_section (sym))))
+ keep = true;
+@@ -1712,7 +1725,21 @@
+ keep = true;
+
+ if (keep && is_strip_section (abfd, bfd_asymbol_section (sym)))
++#ifdef MORPHOS_TARGET
++ {
++ /* If the symbol refers to a stripped section, we still want to
++ * keep it, e.g., _SDA_BASE_ TODO: We should perhaps output a
++ * warning or add another option to trigger this behaviour.
++ * FIXME: The section to which symbol refers must be adjusted
++ * as well */
++ if (!is_specified_symbol (name, keep_specific_htab))
++ {
++ keep = false;
++ }
++ }
++#else
+ keep = false;
++#endif
+
+ if (keep)
+ {
+@@ -2785,8 +2812,10 @@
+ flags &= ~bfd_flags_to_clear;
+ flags &= bfd_applicable_file_flags (obfd);
+
++#ifndef MORPHOS_TARGET
+ if (strip_symbols == STRIP_ALL)
+ flags &= ~HAS_RELOC;
++#endif
+
+ if (!bfd_set_start_address (obfd, start)
+ || !bfd_set_file_flags (obfd, flags))
+@@ -3315,8 +3344,16 @@
+ if (convert_debugging)
+ dhandle = read_debugging_info (ibfd, isympp, symcount, false);
+
++#ifdef MORPHOS_TARGET
++ /* Always mark section symbols used, or else ppc-morphos-strip
++ tries to remove .text etc symbols. Why this happens is unclear.
++ If there's a better way to fix this, feel free to change.
++ - Piru */
++ if (1)
++#else
+ if ((obfd->flags & (EXEC_P | DYNAMIC)) != 0
+ && (obfd->flags & HAS_RELOC) == 0)
++#endif
+ {
+ if (bfd_keep_unused_section_symbols (obfd) || keep_section_symbols)
+ {
+@@ -3372,7 +3409,9 @@
+ haven't been set yet. mark_symbols_used_in_relocations will
+ ignore input sections which have no corresponding output
+ section. */
++#ifndef MORPHOS_TARGET
+ if (strip_symbols != STRIP_ALL)
++#endif
+ {
+ bfd_set_error (bfd_error_no_error);
+ for (asection *s = ibfd->sections; s != NULL; s = s->next)
+@@ -4574,7 +4613,11 @@
+ }
+ }
+
++#ifdef MORPHOS_TARGET
++if(0)
++#else
+ if (strip_symbols == STRIP_ALL)
++#endif
+ {
+ /* Remove relocations which are not in
+ keep_strip_specific_list. */
+@@ -4582,6 +4625,26 @@
+ long i;
+
+ for (w_relpp = relpp, i = 0; i < relcount; i++)
++#ifdef MORPHOS_TARGET
++ if (relpp[i]->sym_ptr_ptr)
++ {
++ asection *sec;
++ sec = bfd_asymbol_section(*relpp[i]->sym_ptr_ptr);
++ if (is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
++ keep_specific_htab))
++ *w_relpp++ = relpp[i];
++ else
++ {
++ /* Don't keep the symbol, but keep the reloc */
++ *w_relpp = relpp[i];
++ (*w_relpp)->addend = bfd_asymbol_value(*relpp [i]->sym_ptr_ptr)
++ - sec->vma
++ + relpp[i]->addend;
++ (*w_relpp)->sym_ptr_ptr = &sec->symbol;
++ w_relpp++;
++ }
++ }
++#else
+ /* PR 17512: file: 9e907e0c. */
+ if (relpp[i]->sym_ptr_ptr
+ /* PR 20096 */
+@@ -4589,6 +4652,7 @@
+ && is_specified_symbol (bfd_asymbol_name (*relpp[i]->sym_ptr_ptr),
+ keep_specific_htab))
+ *w_relpp++ = relpp[i];
++#endif
+ relcount = w_relpp - relpp;
+ *w_relpp = 0;
+ }
+@@ -5045,6 +5109,11 @@
+ if (show_version)
+ print_version ("strip");
+
++#ifdef MORPHOS_TARGET
++ add_specific_symbol("__amigappc__", keep_specific_htab);
++ add_specific_symbol("__abox__", keep_specific_htab);
++#endif
++
+ default_deterministic ();
+
+ /* Default is to strip all symbols. */
+@@ -6142,6 +6211,11 @@
+ if (show_version)
+ print_version ("objcopy");
+
++#ifdef MORPHOS_TARGET
++ add_specific_symbol("__amigappc__", keep_specific_htab);
++ add_specific_symbol("__abox__", keep_specific_htab);
++#endif
++
+ if (interleave && copy_byte == -1)
+ fatal (_("interleave start byte must be set with --byte"));
+
+diff -ruN binutils-2.45/gas/as.c binutils-2.45_mos/gas/as.c
+--- binutils-2.45/gas/as.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/as.c 2025-08-25 21:09:46.151475896 +0300
+@@ -104,6 +104,11 @@
+ MD_AFTER_PARSE_ARGS. */
+ int flag_dwarf_cie_version = -1;
+
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++extern void morphos_add_sdkid_if_missing (void);
++int flag_no_inject_sdkid = 0;
++#endif
++
+ /* The maximum level of DWARF DEBUG information we should manufacture.
+ This defaults to 3 unless overridden by a command line option. */
+ unsigned int dwarf_level = 3;
+@@ -512,6 +517,9 @@
+ OPTION_NOINFO
+ /* When you add options here, check that they do
+ not collide with OPTION_MD_BASE. See as.h. */
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++ ,OPTION_NO_INJECT_SDKID
++#endif
+ };
+
+ static const struct option std_longopts[] =
+@@ -600,6 +608,9 @@
+ ,{"info", no_argument, NULL, OPTION_INFO}
+ ,{"warn", no_argument, NULL, OPTION_WARN}
+ ,{"multibyte-handling", required_argument, NULL, OPTION_MULTIBYTE_HANDLING}
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++ ,{"no-inject-sdkid", no_argument, NULL, OPTION_NO_INJECT_SDKID}
++#endif
+ };
+
+ /* Construct the option lists from the standard list and the target
+@@ -1166,6 +1177,12 @@
+
+ case OPTION_HASH_TABLE_SIZE:
+ break;
++
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++ case OPTION_NO_INJECT_SDKID:
++ flag_no_inject_sdkid = 1;
++ break;
++#endif
+ }
+ }
+
+@@ -1490,6 +1507,11 @@
+ md_finish ();
+ #endif
+
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++ if (! flag_no_inject_sdkid)
++ morphos_add_sdkid_if_missing ();
++#endif
++
+ #if defined OBJ_ELF || defined OBJ_MAYBE_ELF
+ if ((flag_execstack || flag_noexecstack)
+ && OUTPUT_FLAVOR == bfd_target_elf_flavour)
+diff -ruN binutils-2.45/gas/config/obj-elf.c binutils-2.45_mos/gas/config/obj-elf.c
+--- binutils-2.45/gas/config/obj-elf.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/config/obj-elf.c 2025-08-25 19:39:12.022555036 +0300
+@@ -1994,9 +1994,16 @@
+ return NULL;
+
+ gas_assert (symbol_get_value_expression (csym)->X_op == O_constant);
++
++#ifdef MORPHOS_TARGET
++ return fix_new (symbol_get_frag (csym),
++ symbol_get_value_expression (csym)->X_add_number,
++ 0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT, 0);
++#else
+ return fix_new (symbol_get_frag (csym),
+ symbol_get_value_expression (csym)->X_add_number,
+ 0, psym, 0, 0, BFD_RELOC_VTABLE_INHERIT);
++#endif
+ }
+
+ /* This is a version of obj_elf_get_vtable_inherit() that is
+@@ -2037,8 +2044,14 @@
+
+ demand_empty_rest_of_line ();
+
++#ifdef MORPHOS_TARGET
++ return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
++ BFD_RELOC_VTABLE_ENTRY, 0);
++#else
++
+ return fix_new (frag_now, frag_now_fix (), 0, sym, offset, 0,
+ BFD_RELOC_VTABLE_ENTRY);
++#endif
+ }
+
+ /* This is a version of obj_elf_get_vtable_entry() that is
+@@ -2638,6 +2651,69 @@
+ #endif
+ }
+
++#if defined(MORPHOS_TARGET) && defined(MORPHOS_SDK_RELEASE_ID)
++void morphos_add_sdkid_if_missing(void);
++void morphos_add_sdkid_if_missing(void)
++{
++ bool morphos_sdkid_seen = false;
++
++ if (comment_section && seg_not_empty_p (comment_section))
++ {
++ segT old_section = now_seg;
++ int old_subsection = now_subseg;
++ size_t sz;
++ fragS *f;
++ subseg_set (comment_section, 0);
++
++ /* Get last fragment size */
++ sz = frag_now_fix_octets ();
++ /* Calculate total size of the comment section so far */
++ for (f = frchain_now->frch_root; f; f = f->fr_next)
++ {
++ if (f->fr_type != rs_fill)
++ continue;
++ if (frchain_now->frch_last != f)
++ sz += f->fr_fix;
++ }
++
++ if (sz)
++ {
++ char *msg = xmalloc (sz);
++ char *ptr = msg;
++ for (f = frchain_now->frch_root; f; f = f->fr_next)
++ {
++ size_t fix = f == frchain_now->frch_last ? sz : f->fr_fix;
++ if (f->fr_type != rs_fill)
++ continue;
++
++ memcpy (ptr, f->fr_literal, fix);
++ ptr += fix;
++ }
++
++ ptr = memmem (msg, sz, "MorphOS_SDK: ", 13);
++ /* Either at the beginning of section or preceeded by \0 */
++ if (ptr == msg || (ptr && ptr[-1] == '\0'))
++ morphos_sdkid_seen = true;
++
++ free (msg);
++ }
++ subseg_set (old_section, old_subsection);
++ }
++
++ /* If there isn't the SDK ID yet, add it to a .comment section */
++ if (! morphos_sdkid_seen)
++ {
++ char *oldlineptr = input_line_pointer;
++#define xstr_(s) str_(s)
++#define str_(s) #s
++ char data[] = "\"MorphOS_SDK: " xstr_(MORPHOS_SDK_RELEASE_ID) "\"";
++ input_line_pointer = data;
++ obj_elf_ident (0);
++ input_line_pointer = oldlineptr;
++ }
++}
++#endif
++
+ #ifdef INIT_STAB_SECTION
+
+ /* The first entry in a .stabs section is special. */
+diff -ruN binutils-2.45/gas/config/tc-ppc.c binutils-2.45_mos/gas/config/tc-ppc.c
+--- binutils-2.45/gas/config/tc-ppc.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/config/tc-ppc.c 2025-07-27 14:39:08.708060551 +0300
+@@ -279,7 +279,7 @@
+ /* Structure to hold information about predefined registers. */
+ struct pd_reg
+ {
+- char name[6];
++ char name[7];
+ unsigned short value;
+ unsigned short flags;
+ };
+@@ -661,6 +661,8 @@
+ { "v8", 8, PPC_OPERAND_VR },
+ { "v9", 9, PPC_OPERAND_VR },
+
++ { "vrsave", 256, PPC_OPERAND_SPR },
++
+ /* Vector Scalar (VSX) registers (ISA 2.06). */
+ { "vs.0", 0, PPC_OPERAND_VSR },
+ { "vs.1", 1, PPC_OPERAND_VSR },
+@@ -1404,7 +1406,7 @@
+ fprintf (stream, _("\
+ -many generate code for any architecture (PWR/PWRX/PPC)\n"));
+ fprintf (stream, _("\
+--maltivec generate code for AltiVec\n"));
++-maltivec, -mvec generate code for AltiVec\n"));
+ fprintf (stream, _("\
+ -mvsx generate code for Vector-Scalar (VSX) instructions\n"));
+ fprintf (stream, _("\
+@@ -1551,6 +1553,8 @@
+ #ifdef OBJ_ELF
+ # ifdef TE_FreeBSD
+ return (ppc_obj64 ? "elf64-powerpc-freebsd" : "elf32-powerpc-freebsd");
++#elif defined (TE_MORPHOS)
++ return "elf32-morphos";
+ # elif defined (TE_VXWORKS)
+ return "elf32-powerpc-vxworks";
+ # else
+@@ -2157,6 +2161,16 @@
+ MAP ("got@tprel@l", BFD_RELOC_PPC_GOT_TPREL16_LO),
+ MAP ("got@tprel@h", BFD_RELOC_PPC_GOT_TPREL16_HI),
+ MAP ("got@tprel@ha", BFD_RELOC_PPC_GOT_TPREL16_HA),
++
++ /* MorphOS specific relocs */
++ MAP ("drel", BFD_RELOC_PPC_MORPHOS_DREL),
++ MAP ("drell", BFD_RELOC_PPC_MORPHOS_DREL_LO),
++ MAP ("drelh", BFD_RELOC_PPC_MORPHOS_DREL_HI),
++ MAP ("drelha", BFD_RELOC_PPC_MORPHOS_DREL_HA),
++ MAP ("drel@l", BFD_RELOC_PPC_MORPHOS_DREL_LO),
++ MAP ("drel@h", BFD_RELOC_PPC_MORPHOS_DREL_HI),
++ MAP ("drel@ha", BFD_RELOC_PPC_MORPHOS_DREL_HA),
++
+ MAP32 ("fixup", BFD_RELOC_CTOR),
+ MAP32 ("plt", BFD_RELOC_24_PLT_PCREL),
+ MAP32 ("pltrel24", BFD_RELOC_24_PLT_PCREL),
+@@ -3005,8 +3019,6 @@
+ case BFD_RELOC_VTABLE_ENTRY:
+ case BFD_RELOC_VTABLE_INHERIT:
+ break;
+-
+- case BFD_RELOC_8:
+ size = 1;
+ break;
+
+@@ -3112,6 +3124,12 @@
+ case BFD_RELOC_PPC_TPREL16_HA:
+ case BFD_RELOC_PPC_TPREL16_HI:
+ case BFD_RELOC_PPC_TPREL16_LO:
++#ifdef MORPHOS_TARGET
++ case BFD_RELOC_8:
++ case BFD_RELOC_PPC_MORPHOS_DREL_LO:
++ case BFD_RELOC_PPC_MORPHOS_DREL_HI:
++ case BFD_RELOC_PPC_MORPHOS_DREL_HA:
++#endif
+ size = 2;
+ break;
+
+@@ -3176,6 +3194,9 @@
+ case BFD_RELOC_PPC_VLE_SDAREL_LO16D:
+ case BFD_RELOC_PPC64_TLS_PCREL:
+ case BFD_RELOC_RVA:
++#ifdef MORPHOS_TARGET
++ case BFD_RELOC_PPC_MORPHOS_DREL:
++#endif
+ size = 4;
+ break;
+
+@@ -4131,7 +4152,11 @@
+ size,
+ &fixups[i].exp,
+ pcrel,
++#ifdef MORPHOS_TARGET
++ fixups[i].reloc, 0);
++#else
+ fixups[i].reloc);
++#endif
+ }
+ else
+ {
+@@ -4143,7 +4168,11 @@
+ insn_length,
+ &fixups[i].exp,
+ (operand->flags & PPC_OPERAND_RELATIVE) != 0,
++#ifdef MORPHOS_TARGET
++ BFD_RELOC_NONE, 0);
++#else
+ BFD_RELOC_NONE);
++#endif
+ }
+ fixP->fx_pcrel_adjust = fixups[i].opindex;
+ }
+@@ -7645,6 +7674,12 @@
+ case BFD_RELOC_16:
+ case BFD_RELOC_16_PCREL:
+ case BFD_RELOC_8:
++#ifdef MORPHOS_TARGET
++ case BFD_RELOC_PPC_MORPHOS_DREL:
++ case BFD_RELOC_PPC_MORPHOS_DREL_LO:
++ case BFD_RELOC_PPC_MORPHOS_DREL_HI:
++ case BFD_RELOC_PPC_MORPHOS_DREL_HA:
++#endif
+ break;
+
+ default:
+diff -ruN binutils-2.45/gas/config/te-morphos.h binutils-2.45_mos/gas/config/te-morphos.h
+--- binutils-2.45/gas/config/te-morphos.h 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/gas/config/te-morphos.h 2025-07-27 14:39:08.708060551 +0300
+@@ -0,0 +1,14 @@
++/*
++ * te-morphos.h -- MorphOS target environment declarations.
++ */
++
++#define TE_MORPHOS 1
++
++#define LOCAL_LABELS_DOLLAR 1
++#define LOCAL_LABELS_FB 1
++
++#ifdef OBJ_HEADER
++#include OBJ_HEADER
++#else
++#include "obj-format.h"
++#endif
+diff -ruN binutils-2.45/gas/configure.tgt binutils-2.45_mos/gas/configure.tgt
+--- binutils-2.45/gas/configure.tgt 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/configure.tgt 2025-07-27 14:39:08.708060551 +0300
+@@ -357,6 +357,7 @@
+
+ pj*) fmt=elf ;;
+
++ ppc-*-morphos*) fmt=elf em=morphos ;;
+ ppc-*-aix5.[01]) fmt=coff em=aix5 ;;
+ ppc-*-aix[5-9].*) fmt=coff em=aix5 ;;
+ ppc-*-aix*) fmt=coff em=aix ;;
+diff -ruN binutils-2.45/gas/dw2gencfi.c binutils-2.45_mos/gas/dw2gencfi.c
+--- binutils-2.45/gas/dw2gencfi.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/dw2gencfi.c 2025-07-27 14:39:08.708060551 +0300
+@@ -189,8 +189,13 @@
+ char *p = frag_more (size);
+ gas_assert (size == (unsigned) howto->bitsize / 8);
+ md_number_to_chars (p, 0, size);
++#ifdef MORPHOS_TARGET
++ fix_new (frag_now, p - frag_now->fr_literal, size, exp->X_add_symbol,
++ exp->X_add_number, howto->pc_relative, code, 0);
++#else
+ fix_new (frag_now, p - frag_now->fr_literal, size, exp->X_add_symbol,
+ exp->X_add_number, howto->pc_relative, code);
++#endif
+ }
+ else if ((encoding & 0x70) == DW_EH_PE_pcrel)
+ {
+@@ -1422,7 +1427,11 @@
+ exp.X_add_symbol = (symbolS *) local_symbol_make (cseg->name, cseg, frch->frch_root, 0);
+ exp.X_add_number = 0;
+ subseg_set (iseg, ifrch->frch_subseg);
++#ifdef MORPHOS_TARGET
++ fix_new_exp (ifrch->frch_root, 0, 0, &exp, 0, BFD_RELOC_NONE, 0);
++#else
+ fix_new_exp (ifrch->frch_root, 0, 0, &exp, 0, BFD_RELOC_NONE);
++#endif
+
+ /* Restore the original segment info. */
+ subseg_set (cseg, l->subseg);
+@@ -2085,8 +2094,13 @@
+ char *p = frag_more (addr_size);
+ gas_assert (addr_size == (unsigned) howto->bitsize / 8);
+ md_number_to_chars (p, 0, addr_size);
++#ifdef MORPHOS_TARGET
++ fix_new (frag_now, p - frag_now->fr_literal, addr_size,
++ fde->start_address, 0, howto->pc_relative, code, 0);
++#else
+ fix_new (frag_now, p - frag_now->fr_literal, addr_size,
+ fde->start_address, 0, howto->pc_relative, code);
++#endif
+ }
+ else
+ {
+diff -ruN binutils-2.45/gas/read.c binutils-2.45_mos/gas/read.c
+--- binutils-2.45/gas/read.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/read.c 2025-07-27 14:39:08.708060551 +0300
+@@ -4899,9 +4899,14 @@
+ as_bad (_("unsupported BFD relocation size %u"), size);
+ return;
+ }
++#ifdef MORPHOS_TARGET
++ fix_new_exp (frag, p - frag->fr_literal + offset, size,
++ exp, 0, r, 0);
++#else
+ fix_new_exp (frag, p - frag->fr_literal + offset, size,
+ exp, 0, r);
+ #endif
++#endif
+ }
+
+ /* Handle an MRI style string expression. */
+diff -ruN binutils-2.45/gas/write.c binutils-2.45_mos/gas/write.c
+--- binutils-2.45/gas/write.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/write.c 2025-07-27 14:39:08.708060551 +0300
+@@ -136,7 +136,12 @@
+ offsetT offset, /* X_add_number. */
+ int pcrel, /* TRUE if PC-relative relocation. */
+ RELOC_ENUM r_type /* Relocation type. */,
++#ifdef MORPHOS_TARGET
++ int at_beginning, /* Add to the start of the list? */
++ int baserel ATTRIBUTE_UNUSED) /* TRUE if base-relative data */
++#else
+ int at_beginning) /* Add to the start of the list? */
++#endif
+ {
+ fixS *fixP;
+
+@@ -175,6 +180,9 @@
+ #endif
+
+ #ifdef TC_FIX_TYPE
++#ifndef TC_PPC //memo: MORPHOS_TARGET
++ fixP->tc_fix_data = baserel;
++#endif
+ TC_INIT_FIX_DATA (fixP);
+ #endif
+
+@@ -219,10 +227,18 @@
+ symbolS *add_symbol, /* X_add_symbol. */
+ offsetT offset, /* X_add_number. */
+ int pcrel, /* TRUE if PC-relative relocation. */
++#ifdef MORPHOS_TARGET
++ RELOC_ENUM r_type, /* Relocation type. */
++ unsigned long baserel) /* TRUE if base-relative data */
++{
++ return fix_new_internal (frag, where, size, add_symbol,
++ NULL, offset, pcrel, r_type, false, baserel);
++#else
+ RELOC_ENUM r_type /* Relocation type. */)
+ {
+ return fix_new_internal (frag, where, size, add_symbol,
+ NULL, offset, pcrel, r_type, false);
++#endif
+ }
+
+ /* Create a fixup for an expression. Currently we only support fixups
+@@ -235,7 +251,12 @@
+ unsigned long size, /* 1, 2, or 4 usually. */
+ const expressionS *exp, /* Expression. */
+ int pcrel, /* TRUE if PC-relative relocation. */
++#ifdef MORPHOS_TARGET
++ RELOC_ENUM r_type, /* Relocation type. */
++ unsigned long baserel) /* TRUE if base-relative data */
++#else
+ RELOC_ENUM r_type /* Relocation type. */)
++#endif
+ {
+ symbolS *add = NULL;
+ symbolS *sub = NULL;
+@@ -278,8 +299,13 @@
+ break;
+ }
+
++#ifdef MORPHOS_TARGET
++ return fix_new_internal (frag, where, size, add, sub, off, pcrel,
++ r_type, false, baserel);
++#else
+ return fix_new_internal (frag, where, size, add, sub, off, pcrel,
+ r_type, false);
++#endif
+ }
+
+ /* Create a fixup at the beginning of FRAG. The arguments are the same
+@@ -289,8 +315,14 @@
+ fix_at_start (fragS *frag, unsigned long size, symbolS *add_symbol,
+ offsetT offset, int pcrel, RELOC_ENUM r_type)
+ {
++
++#ifdef MORPHOS_TARGET
++ return fix_new_internal (frag, 0, size, add_symbol,
++ NULL, offset, pcrel, r_type, true, 0);
++#else
+ return fix_new_internal (frag, 0, size, add_symbol,
+ NULL, offset, pcrel, r_type, true);
++#endif
+ }
+
+ /* Generic function to determine whether a fixup requires a relocation. */
+@@ -2227,10 +2259,16 @@
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, TC_PARSE_CONS_RETURN_NONE);
+ #else
++#ifdef MORPHOS_TARGET
++ fix_new_exp (lie->frag,
++ lie->word_goes_here - lie->frag->fr_literal,
++ 2, &exp, 0, BFD_RELOC_16, 0);
++#else
+ fix_new_exp (lie->frag,
+ lie->word_goes_here - lie->frag->fr_literal,
+ 2, &exp, 0, BFD_RELOC_16);
+ #endif
++#endif
+ *prevP = lie->next_broken_word;
+ }
+ else
+diff -ruN binutils-2.45/gas/write.h binutils-2.45_mos/gas/write.h
+--- binutils-2.45/gas/write.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/gas/write.h 2025-07-27 14:39:08.708060551 +0300
+@@ -180,12 +180,22 @@
+ extern int relax_segment (struct frag *, segT, int);
+ extern void number_to_chars_littleendian (char *, valueT, int);
+ extern void number_to_chars_bigendian (char *, valueT, int);
++#ifdef MORPHOS_TARGET
++extern fixS *fix_new (fragS *, unsigned long, unsigned long, symbolS *,
++ offsetT, int, bfd_reloc_code_real_type, unsigned long baserel);
++#else
+ extern fixS *fix_new (fragS *, unsigned long, unsigned long, symbolS *,
+ offsetT, int, bfd_reloc_code_real_type);
++#endif
+ extern fixS *fix_at_start (fragS *, unsigned long, symbolS *,
+ offsetT, int, bfd_reloc_code_real_type);
++#ifdef MORPHOS_TARGET
++extern fixS *fix_new_exp (fragS *, unsigned long, unsigned long,
++ const expressionS *, int, bfd_reloc_code_real_type, unsigned long baserel);
++#else
+ extern fixS *fix_new_exp (fragS *, unsigned long, unsigned long,
+ const expressionS *, int, bfd_reloc_code_real_type);
++#endif
+ extern void write_print_statistics (FILE *);
+ extern void as_bad_subtract (fixS *);
+
+diff -ruN binutils-2.45/include/elf/ppc.h binutils-2.45_mos/include/elf/ppc.h
+--- binutils-2.45/include/elf/ppc.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/include/elf/ppc.h 2025-07-27 14:39:08.708060551 +0300
+@@ -133,6 +133,12 @@
+ RELOC_NUMBER (R_PPC_EMB_RELST_HA, 114)
+ RELOC_NUMBER (R_PPC_EMB_BIT_FLD, 115)
+ RELOC_NUMBER (R_PPC_EMB_RELSDA, 116)
++
++/* Special MorphOS relocs. */
++ RELOC_NUMBER (R_PPC_MORPHOS_DREL, 200)
++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_LO, 201)
++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_HI, 202)
++ RELOC_NUMBER (R_PPC_MORPHOS_DREL_HA, 203)
+
+ /* Marker reloc for inline plt call insns. */
+ RELOC_NUMBER (R_PPC_PLTSEQ, 119)
+diff -ruN binutils-2.45/ld/configure.tgt binutils-2.45_mos/ld/configure.tgt
+--- binutils-2.45/ld/configure.tgt 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/configure.tgt 2025-07-27 14:39:08.712060584 +0300
+@@ -803,6 +803,8 @@
+ ;;
+ powerpc-*-haiku*) targ_emul=elf32ppchaiku
+ ;;
++powerpc-*-morphos*) targ_emul=morphos ; targ_extra_emuls=morphos_baserel
++ ;;
+ powerpc-*-windiss*) targ_emul=elf32ppcwindiss
+ ;;
+ pru*-*-*) targ_emul=pruelf
+diff -ruN binutils-2.45/ld/emulparams/morphos_baserel.sh binutils-2.45_mos/ld/emulparams/morphos_baserel.sh
+--- binutils-2.45/ld/emulparams/morphos_baserel.sh 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/ld/emulparams/morphos_baserel.sh 2025-07-27 14:39:08.712060584 +0300
+@@ -0,0 +1,6 @@
++TEMPLATE_NAME=morphos
++SCRIPT_NAME=morphos_baserel
++OUTPUT_FORMAT="elf32-morphos"
++MAXPAGESIZE=0x40000
++ARCH=powerpc
++MACHINE=
+diff -ruN binutils-2.45/ld/emulparams/morphos.sh binutils-2.45_mos/ld/emulparams/morphos.sh
+--- binutils-2.45/ld/emulparams/morphos.sh 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/ld/emulparams/morphos.sh 2025-07-27 14:39:08.712060584 +0300
+@@ -0,0 +1,9 @@
++TEMPLATE_NAME=morphos
++SCRIPT_NAME=morphos
++OUTPUT_FORMAT="elf32-morphos"
++MAXPAGESIZE=0x10000
++TEXT_START_ADDR=0x0
++SEGMENT_SIZE=0x0
++ARCH=powerpc
++MACHINE=
++ENTRY=__start
+diff -ruN binutils-2.45/ld/emultempl/morphos.em binutils-2.45_mos/ld/emultempl/morphos.em
+--- binutils-2.45/ld/emultempl/morphos.em 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/ld/emultempl/morphos.em 2025-07-27 14:39:08.712060584 +0300
+@@ -0,0 +1,1866 @@
++# This shell script emits a C file. -*- C -*-
++# It does some substitutions.
++# ELF emulations.
++test -z "${ELFSIZE}" && ELFSIZE=32
++if [ -z "$MACHINE" ]; then
++ OUTPUT_ARCH=${ARCH}
++else
++ OUTPUT_ARCH=${ARCH}:${MACHINE}
++fi
++fragment <<EOF
++/* This file is is generated by a shell script. DO NOT EDIT! */
++
++/* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME}
++ Copyright (C) 1991-2017 Free Software Foundation, Inc.
++ Written by Steve Chamberlain <sac%cygnus.com@localhost>
++ ELF support by Ian Lance Taylor <ian%cygnus.com@localhost>
++ MorphOS support by Emmanuel Lesueur <lesueur%club-internet.fr@localhost>
++ Additional MorphOS support by Harry Sintonen <sintonen%iki.fi@localhost>
++
++ This file is part of the GNU Binutils.
++
++ 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 3 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., 51 Franklin Street - Fifth Floor, Boston,
++ MA 02110-1301, USA. */
++
++#define TARGET_IS_${EMULATION_NAME}
++
++#include "sysdep.h"
++#include "bfd.h"
++#include "libiberty.h"
++#include "safe-ctype.h"
++#include "filenames.h"
++#include "getopt.h"
++#include <fcntl.h>
++
++#include "bfdlink.h"
++#include "ctf-api.h"
++
++#include "ld.h"
++#include "ldmain.h"
++#include "ldmisc.h"
++#include "ldexp.h"
++#include "ldlang.h"
++#include "ldfile.h"
++#include "ldemul.h"
++#include "ldbuildid.h"
++#include <ldgram.h>
++#include "elf/common.h"
++#include "elf-bfd.h"
++#include "filenames.h"
++#include "elf32-ppc.h"
++#include "ldelfgen.h"
++
++/* Declare functions used by various EXTRA_EM_FILEs. */
++static void gld${EMULATION_NAME}_before_parse (void);
++static void gld${EMULATION_NAME}_after_parse (void);
++static void gld${EMULATION_NAME}_after_open (void);
++static void gld${EMULATION_NAME}_set_symbols (void);
++static void gld${EMULATION_NAME}_before_allocation (void);
++static void gld${EMULATION_NAME}_after_allocation (void);
++static lang_output_section_statement_type *gld${EMULATION_NAME}_place_orphan
++ (asection *, const char *, int);
++EOF
++
++# Import any needed special functions and/or overrides.
++#
++source_em ${srcdir}/emultempl/elf-generic.em
++if test -n "$EXTRA_EM_FILE" ; then
++ source_em ${srcdir}/emultempl/${EXTRA_EM_FILE}.em
++fi
++
++fragment <<EOF
++static int morphos_resident;
++static int morphos_allow_mixed_sdkid;
++
++struct filelistnode
++{
++ struct filelistnode *next;
++ char name[0];
++};
++
++static struct ppc_elf_params params = { PLT_UNSET, 0, -1, 0, 0, 0, 0, 0, 0, 0 };
++
++static void
++ppc_after_open_output (void)
++{
++ if (params.emit_stub_syms < 0)
++ params.emit_stub_syms = (link_info.emitrelocations
++ || bfd_link_pic (&link_info));
++ if (params.pagesize == 0)
++ params.pagesize = link_info.commonpagesize;
++ ppc_elf_link_params (&link_info, ¶ms);
++}
++
++/* Handle MorphOS specific options */
++static bool
++gld${EMULATION_NAME}_parse_args (int argc, char **argv)
++{
++ int prevoptind = optind;
++ int prevopterr = opterr;
++ int indx;
++ int longind;
++ int optc;
++
++#define OPTION_IGNORE (300)
++#define OPTION_MORPHOS_DATADATA_RELOC (OPTION_IGNORE + 1)
++#define OPTION_MORPHOS_BASEREL32 (OPTION_IGNORE + 2)
++#define OPTION_FLAVOR (OPTION_IGNORE + 3)
++#define OPTION_MORPHOS_ALLOW_MIXED_SDKID (OPTION_IGNORE + 4)
++
++ static struct option longopts[] = {
++ {"datadata-reloc", no_argument, NULL, OPTION_MORPHOS_DATADATA_RELOC},
++ /* '\0', NULL, "Relocate for resident program", ONE_DASH },*/
++ {"flavor", required_argument, NULL, OPTION_FLAVOR},
++ /*'\0', NULL, "Select a library flavor", ONE_DASH },*/
++ /*{"baserel32", no_argument, NULL, OPTION_MORPHOS_BASEREL32},*/
++ /* '\0', NULL, "Build a large-data base relative executable", ONE_DASH },*/
++ {"allow-mixed-sdkid", no_argument, NULL, OPTION_MORPHOS_ALLOW_MIXED_SDKID},
++ /*'\0', NULL, "Do not perform SDK ID verification", ONE_DASH },*/
++ {NULL, no_argument, NULL, 0}
++ };
++
++ indx = optind;
++ if (indx == 0)
++ indx = 1;
++
++ opterr = 0;
++ optc = getopt_long_only (argc, argv, "-", longopts, &longind);
++ opterr = prevopterr;
++ switch (optc)
++ {
++ default:
++ optind = prevoptind;
++ return false;
++
++ case 0:
++ /* Long option which just sets a flag. */
++ break;
++
++ case OPTION_MORPHOS_DATADATA_RELOC:
++ morphos_resident=1; /* Write out datadata_reloc array */
++ break;
++
++ /*case OPTION_MORPHOS_BASEREL32:
++ morphos_baserel32=1;
++ break;*/
++
++ case OPTION_FLAVOR:
++ {
++ ldfile_add_flavor (optarg);
++ }
++ break;
++
++ case OPTION_MORPHOS_ALLOW_MIXED_SDKID:
++ morphos_allow_mixed_sdkid=1;
++ break;
++ }
++ return true;
++}
++
++static void
++gld${EMULATION_NAME}_set_symbols (void)
++{
++ if (link_info.strip == strip_all)
++ {
++ link_info.keep_hash = ((struct bfd_hash_table *)
++ xmalloc (sizeof (struct bfd_hash_table)));
++
++ if (! bfd_hash_table_init (link_info.keep_hash, bfd_hash_newfunc, sizeof(struct bfd_hash_entry)))
++ einfo ("%P%F: bfd_hash_table_init failed: %E\n");
++
++ if (bfd_hash_lookup (link_info.keep_hash, "__amigappc__", true, true) == (struct bfd_hash_entry *) NULL
++ || bfd_hash_lookup (link_info.keep_hash, "__abox__", true, true) == (struct bfd_hash_entry *) NULL)
++ einfo ("%P%F: bfd_hash_lookup for insertion failed: %E\n");
++
++ link_info.strip = strip_some;
++ }
++}
++
++EOF
++
++# Functions in this file can be overridden by setting the LDEMUL_* shell
++# variables. If the name of the overriding function is the same as is
++# defined in this file, then don't output this file's version.
++# If a different overriding name is given then output the standard function
++# as presumably it is called from the overriding function.
++#
++if test x"$LDEMUL_BEFORE_PARSE" != xgld"$EMULATION_NAME"_before_parse; then
++fragment <<EOF
++
++static void
++gld${EMULATION_NAME}_before_parse (void)
++{
++ ldfile_set_output_arch ("${OUTPUT_ARCH}", bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`);
++ input_flags.dynamic = ${DYNAMIC_LINK-true};
++ config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`;
++ config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo true ; else echo false ; fi`;
++ `if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
++ link_info.check_relocs_after_open_input = true;
++ link_info.relro = DEFAULT_LD_Z_RELRO;
++ ldfile_sort_flavors();
++}
++
++EOF
++fi
++
++if test x"$LDEMUL_AFTER_PARSE" != xgld"$EMULATION_NAME"_after_parse; then
++fragment <<EOF
++
++static void
++gld${EMULATION_NAME}_after_parse (void)
++{
++ if (bfd_link_pie (&link_info))
++ link_info.flags_1 |= (bfd_vma) DF_1_PIE;
++
++ after_parse_default ();
++}
++
++EOF
++fi
++
++fragment <<EOF
++
++/* These variables are used to implement target options */
++
++static char *audit; /* colon (typically) separated list of libs */
++static char *depaudit; /* colon (typically) separated list of libs */
++
++/* Style of .note.gnu.build-id section. */
++static const char *emit_note_gnu_build_id;
++
++EOF
++
++if test x"$LDEMUL_AFTER_OPEN" != xgld"$EMULATION_NAME"_after_open; then
++fragment <<EOF
++
++static bfd_size_type
++id_note_section_size (bfd *abfd ATTRIBUTE_UNUSED)
++{
++ const char *style = emit_note_gnu_build_id;
++ bfd_size_type size;
++ bfd_size_type build_id_size;
++
++ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
++ size = (size + 3) & -(bfd_size_type) 4;
++
++ build_id_size = compute_build_id_size (style);
++ if (build_id_size)
++ size += build_id_size;
++ else
++ size = 0;
++
++ return size;
++}
++
++static bool
++write_build_id (bfd *abfd)
++{
++ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
++ struct elf_obj_tdata *t = elf_tdata (abfd);
++ const char *style;
++ asection *asec;
++ Elf_Internal_Shdr *i_shdr;
++ unsigned char *contents, *id_bits;
++ bfd_size_type size;
++ file_ptr position;
++ Elf_External_Note *e_note;
++
++ style = t->o->build_id.style;
++ asec = t->o->build_id.sec;
++ if (bfd_is_abs_section (asec->output_section))
++ {
++ einfo (_("%P: warning: .note.gnu.build-id section discarded,"
++ " --build-id ignored.\n"));
++ return true;
++ }
++ i_shdr = &elf_section_data (asec->output_section)->this_hdr;
++
++ if (i_shdr->contents == NULL)
++ {
++ if (asec->contents == NULL)
++ asec->contents = (unsigned char *) xmalloc (asec->size);
++ contents = asec->contents;
++ }
++ else
++ contents = i_shdr->contents + asec->output_offset;
++
++ e_note = (Elf_External_Note *) contents;
++ size = offsetof (Elf_External_Note, name[sizeof "GNU"]);
++ size = (size + 3) & -(bfd_size_type) 4;
++ id_bits = contents + size;
++ size = asec->size - size;
++
++ bfd_h_put_32 (abfd, sizeof "GNU", &e_note->namesz);
++ bfd_h_put_32 (abfd, size, &e_note->descsz);
++ bfd_h_put_32 (abfd, NT_GNU_BUILD_ID, &e_note->type);
++ memcpy (e_note->name, "GNU", sizeof "GNU");
++
++ generate_build_id (abfd, style, bed->s->checksum_contents, id_bits, size);
++
++ position = i_shdr->sh_offset + asec->output_offset;
++ size = asec->size;
++ return (bfd_seek (abfd, position, SEEK_SET) == 0
++ && bfd_write (contents, size, abfd) == size);
++}
++
++/* Make .note.gnu.build-id section, and set up elf_tdata->build_id. */
++
++static bool
++setup_build_id (bfd *ibfd)
++{
++ asection *s;
++ bfd_size_type size;
++ flagword flags;
++
++ size = id_note_section_size (ibfd);
++ if (size == 0)
++ {
++ einfo ("%P: warning: unrecognized --build-id style ignored.\n");
++ return false;
++ }
++
++ flags = (SEC_ALLOC | SEC_LOAD | SEC_IN_MEMORY
++ | SEC_LINKER_CREATED | SEC_READONLY | SEC_DATA);
++ s = bfd_make_section_with_flags (ibfd, ".note.gnu.build-id", flags);
++ if (s != NULL && bfd_set_section_alignment (s, 2))
++ {
++ struct elf_obj_tdata *t = elf_tdata (link_info.output_bfd);
++ t->o->build_id.after_write_object_contents = &write_build_id;
++ t->o->build_id.style = emit_note_gnu_build_id;
++ t->o->build_id.sec = s;
++ elf_section_type (s) = SHT_NOTE;
++ s->size = size;
++ return true;
++ }
++
++ einfo ("%P: warning: Cannot create .note.gnu.build-id section,"
++ " --build-id ignored.\n");
++ return false;
++}
++
++/* This is called after all the input files have been opened. */
++
++static void
++gld${EMULATION_NAME}_after_open (void)
++{
++ struct bfd_link_needed_list *needed, *l;
++ struct elf_link_hash_table *htab;
++ asection *s;
++ bfd *abfd;
++
++ after_open_default ();
++
++ htab = elf_hash_table (&link_info);
++ if (!is_elf_hash_table (&htab->root))
++ return;
++
++ if (command_line.out_implib_filename)
++ {
++ unlink_if_ordinary (command_line.out_implib_filename);
++ link_info.out_implib_bfd
++ = bfd_openw (command_line.out_implib_filename,
++ bfd_get_target (link_info.output_bfd));
++
++ if (link_info.out_implib_bfd == NULL)
++ {
++ einfo ("%F%s: Can't open for writing: %E\n",
++ command_line.out_implib_filename);
++ }
++ }
++
++ if (emit_note_gnu_build_id != NULL)
++ {
++ /* Find an ELF input. */
++ for (abfd = link_info.input_bfds;
++ abfd != (bfd *) NULL; abfd = abfd->link.next)
++ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
++ && bfd_count_sections (abfd) != 0
++ && !((lang_input_statement_type *) abfd->usrdata)->flags.just_syms)
++ break;
++
++ /* PR 10555: If there are no ELF input files do not try to
++ create a .note.gnu-build-id section. */
++ if (abfd == NULL
++ || !setup_build_id (abfd))
++ {
++ free ((char *) emit_note_gnu_build_id);
++ emit_note_gnu_build_id = NULL;
++ }
++ }
++
++ get_elf_backend_data (link_info.output_bfd)->setup_gnu_properties (&link_info);
++
++ if (bfd_link_relocatable (&link_info))
++ {
++ if (link_info.execstack == ! link_info.noexecstack)
++ /* PR ld/16744: If "-z [no]execstack" has been specified on the
++ command line and we are perfoming a relocatable link then no
++ PT_GNU_STACK segment will be created and so the
++ linkinfo.[no]execstack values set in _handle_option() will have no
++ effect. Instead we create a .note.GNU-stack section in much the
++ same way as the assembler does with its --[no]execstack option. */
++ (void) bfd_make_section_with_flags (link_info.input_bfds,
++ ".note.GNU-stack",
++ SEC_READONLY | (link_info.execstack ? SEC_CODE : 0));
++
++ return;
++ }
++
++ if (!link_info.traditional_format)
++ {
++ bfd *elfbfd = NULL;
++ bool warn_eh_frame = false;
++ int seen_type = 0;
++
++ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
++ {
++ int type = 0;
++
++ if (((lang_input_statement_type *) abfd->usrdata)->flags.just_syms)
++ continue;
++
++ for (s = abfd->sections; s && type < COMPACT_EH_HDR; s = s->next)
++ {
++ const char *name = bfd_section_name (s);
++
++ if (bfd_is_abs_section (s->output_section))
++ continue;
++ if (startswith (name, ".eh_frame_entry"))
++ type = COMPACT_EH_HDR;
++ else if (strcmp (name, ".eh_frame") == 0 && s->size > 8)
++ type = DWARF2_EH_HDR;
++ }
++
++ if (type != 0)
++ {
++ if (seen_type == 0)
++ {
++ seen_type = type;
++ }
++ else if (seen_type != type)
++ {
++ einfo (_("%P%F: compact frame descriptions incompatible with"
++ " DWARF2 .eh_frame from %B\n"),
++ type == DWARF2_EH_HDR ? abfd : elfbfd);
++ break;
++ }
++
++ if (!elfbfd
++ && (type == COMPACT_EH_HDR || link_info.eh_frame_hdr_type != 0))
++ {
++ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
++ elfbfd = abfd;
++
++ warn_eh_frame = true;
++ }
++ }
++
++ if (seen_type == COMPACT_EH_HDR)
++ link_info.eh_frame_hdr_type = COMPACT_EH_HDR;
++ }
++ if (elfbfd)
++ {
++ const struct elf_backend_data *bed;
++
++ bed = get_elf_backend_data (elfbfd);
++ s = bfd_make_section_with_flags (elfbfd, ".eh_frame_hdr",
++ bed->dynamic_sec_flags
++ | SEC_READONLY);
++ if (s != NULL
++ && bfd_set_section_alignment (s, 2))
++ {
++ htab->eh_info.hdr_sec = s;
++ warn_eh_frame = false;
++ }
++ }
++ if (warn_eh_frame)
++ einfo ("%P: warning: Cannot create .eh_frame_hdr section,"
++ " --eh-frame-hdr ignored.\n");
++ }
++
++ /* Get the list of files which appear in DT_NEEDED entries in
++ dynamic objects included in the link (often there will be none).
++ For each such file, we want to track down the corresponding
++ library, and include the symbol table in the link. This is what
++ the runtime dynamic linker will do. Tracking the files down here
++ permits one dynamic object to include another without requiring
++ special action by the person doing the link. Note that the
++ needed list can actually grow while we are stepping through this
++ loop. */
++ needed = bfd_elf_get_needed_list (link_info.output_bfd, &link_info);
++ for (l = needed; l != NULL; l = l->next)
++ {
++ struct bfd_link_needed_list *ll;
++
++ /* If we've already seen this file, skip it. */
++ for (ll = needed; ll != l; ll = ll->next)
++ if (strcmp (ll->name, l->name) == 0)
++ break;
++ if (ll != l)
++ continue;
++
++ einfo ("%P: warning: %s, needed by %B, not found (try using -rpath or -rpath-link)\n",
++ l->name, l->by);
++ }
++
++ if (link_info.eh_frame_hdr_type == COMPACT_EH_HDR)
++ if (!bfd_elf_parse_eh_frame_entries (NULL, &link_info))
++ einfo (_("%P%F: Failed to parse EH frame entries.\n"));
++
++
++ /* If final executable linking, perform checks against SDK version mixing */
++ if (!morphos_allow_mixed_sdkid && bfd_link_executable (&link_info))
++ {
++ struct filelistnode *bfd_without_sdk_id = NULL;
++ struct filelistnode *nextnodep = NULL;
++ bool mixed_linkage = false;
++ bool linking_with_libnix = false;
++ char *sdk_id = NULL;
++
++ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
++ {
++ bool progbits_seen = false;
++ bool id_seen = false;
++
++ if (bfd_get_flavour (abfd) != bfd_target_elf_flavour)
++ continue;
++
++ if (abfd->my_archive != NULL
++ && !bfd_is_thin_archive (abfd->my_archive))
++ {
++ const char *archivename = bfd_get_filename (abfd->my_archive);
++ size_t namelen = strlen(archivename);
++
++ if (namelen >= 14 && strcmp (archivename + namelen - 14, "/libnix/libc.a") == 0)
++ linking_with_libnix = true;
++ /* Whitelist libgcc.a from checking */
++ else if (namelen >= 9 && strcmp (archivename + namelen - 9, "/libgcc.a") == 0)
++ continue;
++ }
++
++ for (s = abfd->sections; s; s = s->next)
++ {
++ const char *name = bfd_section_name (s);
++ ssize_t sz;
++ char *msg, *ptr;
++
++ if (elf_section_type (s) == SHT_PROGBITS && (s->flags & SEC_CODE))
++ progbits_seen = true;
++
++ if (strcmp (name, ".comment") != 0 || s->size == 0)
++ continue;
++
++ sz = s->size;
++ msg = (char *) xmalloc ((size_t) (sz + 1));
++ if (! bfd_get_section_contents (abfd, s, msg,
++ (file_ptr) 0, sz))
++ {
++ free (msg);
++ einfo ("%P: Can't read %pB contents of section .comment: %E\n",
++ abfd);
++ continue;
++ }
++ msg[sz] = '\0';
++ ptr = msg;
++ do
++ {
++ char *p = strchr (ptr, '\0');
++ char *id = ptr;
++
++ if (! p)
++ p = msg + sz;
++ sz -= p + 1 - ptr;
++ ptr = p + 1;
++ if (strncmp (id, "MorphOS_SDK: ", 13) != 0)
++ continue;
++ id += 13;
++ id_seen = true;
++
++ /* If wildcard ID is specified, back out from all checking */
++ if (strcmp (id, "*") == 0)
++ goto wildout;
++
++ if (sdk_id)
++ {
++ /* Do we have mixed SDK ID? */
++ if (strcmp (sdk_id, id) != 0)
++ {
++ einfo ("%P: the MorphOS SDK identification %s from %pB"
++ " different from expected identification %s\n",
++ id, abfd, sdk_id);
++ mixed_linkage = true;
++ break;
++ }
++ }
++ else
++ {
++ /* If we have seen bfd without SDK identication, this is
++ mixed linking. */
++ if (bfd_without_sdk_id)
++ {
++ if (! mixed_linkage)
++ {
++ const struct filelistnode *n;
++ einfo ("%P: The MorphOS SDK identification %s is missing"
++ " from object file(s): ",
++ id);
++ for (n = bfd_without_sdk_id; n; n = n->next)
++ {
++ einfo ("%s%s", n->name, n->next ? ", " : ".\n");
++ }
++ mixed_linkage = true;
++ }
++ break;
++ }
++ sdk_id = xstrdup (id);
++ }
++ } while ( sz > 0);
++ free (msg);
++ }
++
++ /* If SDK identification has been seen, but this bfd omits it,
++ this is mixed linking. */
++ if ( !mixed_linkage && sdk_id && progbits_seen && !id_seen)
++ {
++ mixed_linkage = true;
++ einfo ("%P: The MorphOS SDK identification omitted from %pB\n",
++ abfd);
++ }
++ /* If bfd included "program" parts but didn't include the SDK ID
++ note this for other check rounds (see above). */
++ else if (progbits_seen && !id_seen)
++ {
++ const char *archivename = abfd->my_archive != NULL
++ && !bfd_is_thin_archive (abfd->my_archive) ? bfd_get_filename(abfd->my_archive) :
++ NULL;
++ const char *name = bfd_get_filename(abfd);
++ struct filelistnode *fln;
++ if (archivename)
++ {
++ fln = xmalloc (sizeof(*fln) + strlen (archivename) + 2 + strlen (name) + 1);
++ sprintf (fln->name, "%s(%s)", archivename, name);
++ }
++ else
++ {
++ fln = xmalloc (sizeof(*fln) + strlen(name) + 1);
++ strcpy (fln->name, name);
++ }
++ fln->next = NULL;
++ if (nextnodep)
++ nextnodep->next = fln;
++ else
++ bfd_without_sdk_id = fln;
++ nextnodep = fln;
++ }
++ }
++ if (mixed_linkage)
++ {
++ void (*mfunc)(const char *, ...);
++ const char *extra;
++ if (linking_with_libnix)
++ {
++ /* Outright fail the link operation */
++ mfunc = fatal;
++ extra = ", in specific linking against libc is dangerous";
++ }
++ else
++ {
++ /* Warn the user about potential issues */
++ mfunc = einfo;
++ extra = "";
++ }
++ mfunc ("%P: Mixing object files and linklibs compiled with"
++ " different SDK versions may result in unexpected"
++ " behaviour and crashes%s. If in doubt rebuild all files"
++ " with the current SDK. Consult the SDK documentation"
++ " for further details.\n", extra);
++ }
++wildout:
++ free (sdk_id);
++ for (nextnodep = bfd_without_sdk_id; nextnodep; )
++ {
++ void *p = nextnodep;
++ nextnodep = nextnodep->next;
++ free (p);
++ }
++ }
++}
++
++EOF
++fi
++
++fragment <<EOF
++
++/* Look through an expression for an assignment statement. */
++
++static void
++gld${EMULATION_NAME}_find_exp_assignment (etree_type *exp)
++{
++ bool provide = false;
++
++ switch (exp->type.node_class)
++ {
++ case etree_provide:
++ case etree_provided:
++ provide = true;
++ /* Fallthru */
++ case etree_assign:
++ /* We call record_link_assignment even if the symbol is defined.
++ This is because if it is defined by a dynamic object, we
++ actually want to use the value defined by the linker script,
++ not the value from the dynamic object (because we are setting
++ symbols like etext). If the symbol is defined by a regular
++ object, then, as it happens, calling record_link_assignment
++ will do no harm. */
++ if (strcmp (exp->assign.dst, ".") != 0)
++ {
++ if (!bfd_elf_record_link_assignment (link_info.output_bfd,
++ &link_info,
++ exp->assign.dst, provide,
++ exp->assign.hidden))
++ einfo ("%P%F: failed to record assignment to %s: %E\n",
++ exp->assign.dst);
++ }
++ gld${EMULATION_NAME}_find_exp_assignment (exp->assign.src);
++ break;
++
++ case etree_binary:
++ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.lhs);
++ gld${EMULATION_NAME}_find_exp_assignment (exp->binary.rhs);
++ break;
++
++ case etree_trinary:
++ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.cond);
++ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.lhs);
++ gld${EMULATION_NAME}_find_exp_assignment (exp->trinary.rhs);
++ break;
++
++ case etree_unary:
++ gld${EMULATION_NAME}_find_exp_assignment (exp->unary.child);
++ break;
++
++ default:
++ break;
++ }
++}
++
++
++/* This is called by the before_allocation routine via
++ lang_for_each_statement. It locates any assignment statements, and
++ tells the ELF backend about them, in case they are assignments to
++ symbols which are referred to by dynamic objects. */
++
++static void
++gld${EMULATION_NAME}_find_statement_assignment (lang_statement_union_type *s)
++{
++ if (s->header.type == lang_assignment_statement_enum)
++ gld${EMULATION_NAME}_find_exp_assignment (s->assignment_statement.exp);
++}
++
++EOF
++
++if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then
++ if test x"${ELF_INTERPRETER_NAME+set}" = xset; then
++ ELF_INTERPRETER_SET_DEFAULT="
++ if (sinterp != NULL)
++ {
++ sinterp->contents = (unsigned char *) ${ELF_INTERPRETER_NAME};
++ sinterp->size = strlen ((char *) sinterp->contents) + 1;
++ }
++
++"
++ else
++ ELF_INTERPRETER_SET_DEFAULT=
++ fi
++fragment <<EOF
++
++/* used by before_allocation and handle_option. */
++static void
++gld${EMULATION_NAME}_append_to_separated_string (char **to, char *op_arg)
++{
++ if (*to == NULL)
++ *to = xstrdup (op_arg);
++ else
++ {
++ size_t to_len = strlen (*to);
++ size_t op_arg_len = strlen (op_arg);
++ char *buf;
++ char *cp = *to;
++
++ /* First see whether OPTARG is already in the path. */
++ do
++ {
++ if (strncmp (op_arg, cp, op_arg_len) == 0
++ && (cp[op_arg_len] == 0
++ || cp[op_arg_len] == config.rpath_separator))
++ /* We found it. */
++ break;
++
++ /* Not yet found. */
++ cp = strchr (cp, config.rpath_separator);
++ if (cp != NULL)
++ ++cp;
++ }
++ while (cp != NULL);
++
++ if (cp == NULL)
++ {
++ buf = xmalloc (to_len + op_arg_len + 2);
++ sprintf (buf, "%s%c%s", *to,
++ config.rpath_separator, op_arg);
++ free (*to);
++ *to = buf;
++ }
++ }
++}
++
++#if defined(__GNUC__) && GCC_VERSION < 4006
++ /* Work around a GCC uninitialized warning bug fixed in GCC 4.6. */
++static struct bfd_link_hash_entry ehdr_start_empty;
++#endif
++
++/* This is called after the sections have been attached to output
++ sections, but before any sizes or addresses have been set. */
++
++static void
++gld${EMULATION_NAME}_before_allocation (void)
++{
++ const char *rpath;
++ asection *sinterp;
++ bfd *abfd;
++ struct elf_link_hash_entry *ehdr_start = NULL;
++#if defined(__GNUC__) && GCC_VERSION < 4006
++ /* Work around a GCC uninitialized warning bug fixed in GCC 4.6. */
++ struct bfd_link_hash_entry ehdr_start_save = ehdr_start_empty;
++#else
++ struct bfd_link_hash_entry ehdr_start_save;
++#endif
++
++ if (is_elf_hash_table (link_info.hash))
++ {
++ _bfd_elf_tls_setup (link_info.output_bfd, &link_info);
++
++ /* Make __ehdr_start hidden if it has been referenced, to
++ prevent the symbol from being dynamic. */
++ if (!bfd_link_relocatable (&link_info))
++ {
++ struct elf_link_hash_entry *h
++ = elf_link_hash_lookup (elf_hash_table (&link_info), "__ehdr_start",
++ false, false, true);
++
++ /* Only adjust the export class if the symbol was referenced
++ and not defined, otherwise leave it alone. */
++ if (h != NULL
++ && (h->root.type == bfd_link_hash_new
++ || h->root.type == bfd_link_hash_undefined
++ || h->root.type == bfd_link_hash_undefweak
++ || h->root.type == bfd_link_hash_common))
++ {
++ _bfd_elf_link_hash_hide_symbol (&link_info, h, true);
++ if (ELF_ST_VISIBILITY (h->other) != STV_INTERNAL)
++ h->other = (h->other & ~ELF_ST_VISIBILITY (-1)) | STV_HIDDEN;
++ /* Don't leave the symbol undefined. Undefined hidden
++ symbols typically won't have dynamic relocations, but
++ we most likely will need dynamic relocations for
++ __ehdr_start if we are building a PIE or shared
++ library. */
++ ehdr_start = h;
++ ehdr_start_save = h->root;
++ h->root.type = bfd_link_hash_defined;
++ h->root.u.def.section = bfd_abs_section_ptr;
++ h->root.u.def.value = 0;
++ }
++ }
++
++ /* If we are going to make any variable assignments, we need to
++ let the ELF backend know about them in case the variables are
++ referred to by dynamic objects. */
++ lang_for_each_statement (gld${EMULATION_NAME}_find_statement_assignment);
++ /* Add the data->data relocation table... */
++ if (morphos_resident)
++ {
++ asection *sec = bfd_make_section(link_info.output_bfd, "ddrelocs");
++ struct bfd_link_hash_entry *sym;
++
++ if (sec)
++ {
++ bfd_set_section_flags(sec, SEC_ALLOC | SEC_LOAD | SEC_READONLY |
++ SEC_DATA | SEC_HAS_CONTENTS);
++ sec->output_section = sec;
++ sec->output_offset = 0;
++ sym = bfd_link_hash_lookup(link_info.hash, "__datadata_relocs", true, false, false);
++ if (sym)
++ {
++ sym->type = bfd_link_hash_defined;
++ sym->u.def.value = 0;
++ sym->u.def.section = sec;
++ }
++ }
++ }
++ }
++
++ /* Let the ELF backend work out the sizes of any sections required
++ by dynamic linking. */
++ rpath = command_line.rpath;
++// if (rpath == NULL)
++// rpath = (const char *) getenv ("LD_RUN_PATH");
++
++ for (abfd = link_info.input_bfds; abfd; abfd = abfd->link.next)
++ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
++ {
++ const char *audit_libs = elf_dt_audit (abfd);
++
++ /* If the input bfd contains an audit entry, we need to add it as
++ a dep audit entry. */
++ if (audit_libs && *audit_libs != '\0')
++ {
++ char *cp = xstrdup (audit_libs);
++ do
++ {
++ int more = 0;
++ char *cp2 = strchr (cp, config.rpath_separator);
++
++ if (cp2)
++ {
++ *cp2 = '\0';
++ more = 1;
++ }
++
++ if (cp != NULL && *cp != '\0')
++ gld${EMULATION_NAME}_append_to_separated_string (&depaudit, cp);
++
++ cp = more ? ++cp2 : NULL;
++ }
++ while (cp != NULL);
++ }
++ }
++
++ if (! (bfd_elf_size_dynamic_sections
++ (link_info.output_bfd, command_line.soname, rpath,
++ command_line.filter_shlib, audit, depaudit,
++ (const char * const *) command_line.auxiliary_filters,
++ &link_info, &sinterp)))
++ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
++
++${ELF_INTERPRETER_SET_DEFAULT}
++ /* Let the user override the dynamic linker we are using. */
++ if (command_line.interpreter != NULL
++ && sinterp != NULL)
++ {
++ sinterp->contents = (bfd_byte *) command_line.interpreter;
++ sinterp->size = strlen (command_line.interpreter) + 1;
++ }
++
++ /* Look for any sections named .gnu.warning. As a GNU extensions,
++ we treat such sections as containing warning messages. We print
++ out the warning message, and then zero out the section size so
++ that it does not get copied into the output file. */
++
++ {
++ LANG_FOR_EACH_INPUT_STATEMENT (is)
++ {
++ asection *s;
++ bfd_size_type sz;
++ char *msg;
++
++ if (is->flags.just_syms)
++ continue;
++
++ s = bfd_get_section_by_name (is->the_bfd, ".gnu.warning");
++ if (s == NULL)
++ continue;
++
++ sz = s->size;
++ msg = (char *) xmalloc ((size_t) (sz + 1));
++ if (! bfd_get_section_contents (is->the_bfd, s, msg,
++ (file_ptr) 0, sz))
++ einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n",
++ is->the_bfd);
++ msg[sz] = '\0';
++ (*link_info.callbacks->warning) (&link_info, msg,
++ (const char *) NULL, is->the_bfd,
++ (asection *) NULL, (bfd_vma) 0);
++ free (msg);
++
++ /* Clobber the section size, so that we don't waste space
++ copying the warning into the output file. If we've already
++ sized the output section, adjust its size. The adjustment
++ is on rawsize because targets that size sections early will
++ have called lang_reset_memory_regions after sizing. */
++ if (s->output_section != NULL
++ && s->output_section->rawsize >= s->size)
++ s->output_section->rawsize -= s->size;
++
++ s->size = 0;
++
++ /* Also set SEC_EXCLUDE, so that local symbols defined in the
++ warning section don't get copied to the output. */
++ s->flags |= SEC_EXCLUDE | SEC_KEEP;
++ }
++ }
++
++ before_allocation_default ();
++
++ if (!bfd_elf_size_dynsym_hash_dynstr (link_info.output_bfd, &link_info))
++ einfo ("%P%F: failed to set dynamic section sizes: %E\n");
++
++ if (ehdr_start != NULL)
++ {
++ /* If we twiddled __ehdr_start to defined earlier, put it back
++ as it was. */
++ ehdr_start->root.type = ehdr_start_save.type;
++ ehdr_start->root.u = ehdr_start_save.u;
++ }
++
++ ENABLE_RELAXATION;
++ params.branch_trampolines = 1;
++}
++
++EOF
++fi
++
++if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then
++fragment <<EOF
++
++/* A variant of lang_output_section_find used by place_orphan. */
++
++static lang_output_section_statement_type *
++output_rel_find (int isdyn, int rela)
++{
++ lang_output_section_statement_type *lookup;
++ lang_output_section_statement_type *last = NULL;
++ lang_output_section_statement_type *last_alloc = NULL;
++ lang_output_section_statement_type *last_ro_alloc = NULL;
++ lang_output_section_statement_type *last_rel = NULL;
++ lang_output_section_statement_type *last_rel_alloc = NULL;
++
++ for (lookup = &lang_os_list.head->output_section_statement;
++ lookup != NULL;
++ lookup = lookup->next)
++ {
++ if (lookup->constraint >= 0
++ && startswith (lookup->name, ".rel"))
++ {
++ int lookrela = lookup->name[4] == 'a';
++
++ /* .rel.dyn must come before all other reloc sections, to suit
++ GNU ld.so. */
++ if (isdyn)
++ break;
++
++ /* Don't place after .rel.plt as doing so results in wrong
++ dynamic tags. */
++ if (strcmp (".plt", lookup->name + 4 + lookrela) == 0)
++ break;
++
++ if (rela == lookrela || last_rel == NULL)
++ last_rel = lookup;
++ if ((rela == lookrela || last_rel_alloc == NULL)
++ && lookup->bfd_section != NULL
++ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
++ last_rel_alloc = lookup;
++ }
++
++ last = lookup;
++ if (lookup->bfd_section != NULL
++ && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
++ {
++ last_alloc = lookup;
++ if ((lookup->bfd_section->flags & SEC_READONLY) != 0)
++ last_ro_alloc = lookup;
++ }
++ }
++
++ if (last_rel_alloc)
++ return last_rel_alloc;
++
++ if (last_rel)
++ return last_rel;
++
++ if (last_ro_alloc)
++ return last_ro_alloc;
++
++ if (last_alloc)
++ return last_alloc;
++
++ return last;
++}
++
++/* Place an orphan section. We use this to put random SHF_ALLOC
++ sections in the right segment. */
++
++static lang_output_section_statement_type *
++gld${EMULATION_NAME}_place_orphan (asection *s,
++ const char *secname,
++ int constraint)
++{
++ static struct orphan_save hold[] =
++ {
++ { ".text",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE,
++ 0, 0, 0, 0 },
++ { ".rodata",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
++ 0, 0, 0, 0 },
++ { ".tdata",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_THREAD_LOCAL,
++ 0, 0, 0, 0 },
++ { ".data",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA,
++ 0, 0, 0, 0 },
++ { ".bss",
++ SEC_ALLOC,
++ 0, 0, 0, 0 },
++ { 0,
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
++ 0, 0, 0, 0 },
++ { ".interp",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA,
++ 0, 0, 0, 0 },
++ { ".sdata",
++ SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_SMALL_DATA,
++ 0, 0, 0, 0 },
++ { ".comment",
++ SEC_HAS_CONTENTS,
++ 0, 0, 0, 0 },
++ };
++ enum orphan_save_index
++ {
++ orphan_text = 0,
++ orphan_rodata,
++ orphan_tdata,
++ orphan_data,
++ orphan_bss,
++ orphan_rel,
++ orphan_interp,
++ orphan_sdata,
++ orphan_nonalloc
++ };
++ static int orphan_init_done = 0;
++ struct orphan_save *place;
++ lang_output_section_statement_type *after;
++ lang_output_section_statement_type *os;
++ lang_output_section_statement_type *match_by_name = NULL;
++ int isdyn = 0;
++ int iself = s->owner->xvec->flavour == bfd_target_elf_flavour;
++ unsigned int sh_type = iself ? elf_section_type (s) : SHT_NULL;
++ flagword flags;
++ asection *nexts;
++
++ if (!bfd_link_relocatable (&link_info)
++ && link_info.combreloc
++ && (s->flags & SEC_ALLOC))
++ {
++ if (iself)
++ switch (sh_type)
++ {
++ case SHT_RELA:
++ secname = ".rela.dyn";
++ isdyn = 1;
++ break;
++ case SHT_REL:
++ secname = ".rel.dyn";
++ isdyn = 1;
++ break;
++ default:
++ break;
++ }
++ else if (startswith (secname, ".rel"))
++ {
++ secname = secname[4] == 'a' ? ".rela.dyn" : ".rel.dyn";
++ isdyn = 1;
++ }
++ }
++
++ if (!bfd_link_relocatable (&link_info)
++ && (s->flags & SEC_ALLOC) != 0
++ && (elf_section_flags (s) & SHF_GNU_MBIND) != 0)
++ {
++ /* Find the output mbind section with the same type, attributes
++ and sh_info field. */
++ for (os = (void *) lang_os_list.head;
++ os != NULL;
++ os = os->next)
++ if (os->bfd_section != NULL
++ && !bfd_is_abs_section (os->bfd_section)
++ && (elf_section_flags (os->bfd_section) & SHF_GNU_MBIND) != 0
++ && ((s->flags & (SEC_ALLOC
++ | SEC_LOAD
++ | SEC_HAS_CONTENTS
++ | SEC_READONLY
++ | SEC_CODE))
++ == (os->bfd_section->flags & (SEC_ALLOC
++ | SEC_LOAD
++ | SEC_HAS_CONTENTS
++ | SEC_READONLY
++ | SEC_CODE)))
++ && (elf_section_data (os->bfd_section)->this_hdr.sh_info
++ == elf_section_data (s)->this_hdr.sh_info))
++ {
++ lang_add_section (&os->children, s, NULL, NULL, os);
++ return os;
++ }
++
++ /* Create the output mbind section with the ".mbind." prefix
++ in section name. */
++ if ((s->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
++ secname = ".mbind.bss";
++ else if ((s->flags & SEC_READONLY) == 0)
++ secname = ".mbind.data";
++ else if ((s->flags & SEC_CODE) == 0)
++ secname = ".mbind.rodata";
++ else
++ secname = ".mbind.text";
++ }
++
++ /* Look through the script to see where to place this section. */
++ if (constraint == 0)
++ for (os = lang_output_section_find (secname);
++ os != NULL;
++ os = next_matching_output_section_statement (os, 0))
++ {
++ /* If we don't match an existing output section, tell
++ lang_insert_orphan to create a new output section. */
++ constraint = SPECIAL;
++
++ /* SEC_EXCLUDE is cleared when doing a relocatable link. But
++ we can't merge 2 input sections with the same name when only
++ one of them has SHF_EXCLUDE. Don't merge 2 sections with
++ different sh_info. */
++ if (os->bfd_section != NULL
++ && (elf_section_data (os->bfd_section)->this_hdr.sh_info
++ == elf_section_data (s)->this_hdr.sh_info)
++ && (os->bfd_section->flags == 0
++ || ((!bfd_link_relocatable (&link_info)
++ || (iself && (((elf_section_flags (s)
++ ^ elf_section_flags (os->bfd_section))
++ & SHF_EXCLUDE) == 0)))
++ && ((s->flags ^ os->bfd_section->flags)
++ & (SEC_LOAD | SEC_ALLOC)) == 0
++ && _bfd_elf_match_sections_by_type (link_info.output_bfd,
++ os->bfd_section,
++ s->owner, s))))
++ {
++ /* We already have an output section statement with this
++ name, and its bfd section has compatible flags.
++ If the section already exists but does not have any flags
++ set, then it has been created by the linker, probably as a
++ result of a --section-start command line switch. */
++ lang_add_section (&os->children, s, NULL, NULL, os);
++ return os;
++ }
++
++ /* Save unused output sections in case we can match them
++ against orphans later. */
++ if (os->bfd_section == NULL)
++ match_by_name = os;
++ }
++
++ /* If we didn't match an active output section, see if we matched an
++ unused one and use that. */
++ if (match_by_name)
++ {
++ lang_add_section (&match_by_name->children, s, NULL, NULL, match_by_name);
++ return match_by_name;
++ }
++
++ if (!orphan_init_done)
++ {
++ struct orphan_save *ho;
++
++ for (ho = hold; ho < hold + sizeof (hold) / sizeof (hold[0]); ++ho)
++ if (ho->name != NULL)
++ {
++ ho->os = lang_output_section_find (ho->name);
++ if (ho->os != NULL && ho->os->flags == 0)
++ ho->os->flags = ho->flags;
++ }
++ orphan_init_done = 1;
++ }
++
++ /* If this is a final link, then always put .gnu.warning.SYMBOL
++ sections into the .text section to get them out of the way. */
++ if (bfd_link_executable (&link_info)
++ && startswith (s->name, ".gnu.warning.")
++ && hold[orphan_text].os != NULL)
++ {
++ os = hold[orphan_text].os;
++ lang_add_section (&os->children, s, NULL, NULL, os);
++ return os;
++ }
++
++ flags = s->flags;
++ if (!bfd_link_relocatable (&link_info))
++ {
++ nexts = s;
++ while ((nexts = bfd_get_next_section_by_name (nexts->owner, nexts))
++ != NULL)
++ if (nexts->output_section == NULL
++ && (nexts->flags & SEC_EXCLUDE) == 0
++ && ((nexts->flags ^ flags) & (SEC_LOAD | SEC_ALLOC)) == 0
++ && (nexts->owner->flags & DYNAMIC) == 0
++ && nexts->owner->usrdata != NULL
++ && !(((lang_input_statement_type *) nexts->owner->usrdata)
++ ->flags.just_syms)
++ && _bfd_elf_match_sections_by_type (nexts->owner, nexts,
++ s->owner, s))
++ flags = (((flags ^ SEC_READONLY)
++ | (nexts->flags ^ SEC_READONLY))
++ ^ SEC_READONLY);
++ }
++
++ /* Decide which segment the section should go in based on the
++ section name and section flags. We put loadable .note sections
++ right after the .interp section, so that the PT_NOTE segment is
++ stored right after the program headers where the OS can read it
++ in the first page. */
++
++ place = NULL;
++ if ((flags & (SEC_ALLOC | SEC_DEBUGGING)) == 0)
++ place = &hold[orphan_nonalloc];
++ else if ((flags & SEC_ALLOC) == 0)
++ ;
++ else if ((flags & SEC_LOAD) != 0
++ && ((iself && sh_type == SHT_NOTE)
++ || (!iself && startswith (secname, ".note"))))
++ place = &hold[orphan_interp];
++ else if ((flags & (SEC_LOAD | SEC_HAS_CONTENTS | SEC_THREAD_LOCAL)) == 0)
++ place = &hold[orphan_bss];
++ else if ((flags & SEC_SMALL_DATA) != 0)
++ place = &hold[orphan_sdata];
++ else if ((flags & SEC_THREAD_LOCAL) != 0)
++ place = &hold[orphan_tdata];
++ else if ((flags & SEC_READONLY) == 0)
++ place = &hold[orphan_data];
++ else if (((iself && (sh_type == SHT_RELA || sh_type == SHT_REL))
++ || (!iself && startswith (secname, ".rel")))
++ && (flags & SEC_LOAD) != 0)
++ place = &hold[orphan_rel];
++ else if ((flags & SEC_CODE) == 0)
++ place = &hold[orphan_rodata];
++ else
++ place = &hold[orphan_text];
++
++ after = NULL;
++ if (place != NULL)
++ {
++ if (place->os == NULL)
++ {
++ if (place->name != NULL)
++ place->os = lang_output_section_find (place->name);
++ else
++ {
++ int rela = /*elfinput ? sh_type == SHT_RELA :*/secname[4] == 'a';
++ place->os = output_rel_find (isdyn, rela);
++ }
++ }
++ after = place->os;
++ if (after == NULL)
++ after
++ = lang_output_section_find_by_flags (s, flags, &place->os,
++ _bfd_elf_match_sections_by_type);
++ if (after == NULL)
++ /* *ABS* is always the first output section statement. */
++ after = &lang_os_list.head->output_section_statement;
++ }
++
++ return lang_insert_orphan (s, secname, constraint, after, place, NULL, NULL);
++}
++EOF
++fi
++
++if test x"$LDEMUL_AFTER_ALLOCATION" != xgld"$EMULATION_NAME"_after_allocation; then
++fragment <<EOF
++
++static void
++gld${EMULATION_NAME}_after_allocation (void)
++{
++ int need_layout = bfd_elf_discard_info (link_info.output_bfd, &link_info);
++
++ if (need_layout < 0)
++ einfo ("%X%P: .eh_frame/.stab edit: %E\n");
++ else
++ ldelf_map_segments (need_layout);
++}
++EOF
++fi
++
++if test x"$LDEMUL_GET_SCRIPT" != xgld"$EMULATION_NAME"_get_script; then
++fragment <<EOF
++
++static char *
++gld${EMULATION_NAME}_get_script (int *isfile)
++EOF
++
++if test x"$COMPILE_IN" = xyes
++then
++# Scripts compiled in.
++
++# sed commands to quote an ld script as a C string.
++sc="-f ${srcdir}/emultempl/stringify.sed"
++
++fragment <<EOF
++{
++ *isfile = 0;
++
++ if (bfd_link_relocatable (&link_info) && config.build_constructors)
++ return
++EOF
++sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
++echo ' ; else if (bfd_link_relocatable (&link_info)) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
++if test -n "$GENERATE_PIE_SCRIPT" ; then
++if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
++echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c
++echo ' && link_info.combreloc' >> e${EMULATION_NAME}.c
++echo ' && link_info.relro' >> e${EMULATION_NAME}.c
++echo ' && (link_info.flags & DF_BIND_NOW)) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xdw >> e${EMULATION_NAME}.c
++echo ' ; else if (bfd_link_pie (&link_info)' >> e${EMULATION_NAME}.c
++echo ' && link_info.combreloc) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xdc >> e${EMULATION_NAME}.c
++fi
++echo ' ; else if (bfd_link_pie (&link_info)) return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.xd >> e${EMULATION_NAME}.c
++fi
++echo ' ; else return' >> e${EMULATION_NAME}.c
++sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
++echo '; }' >> e${EMULATION_NAME}.c
++
++else
++# Scripts read from the filesystem.
++
++fragment <<EOF
++{
++ *isfile = 1;
++
++ if (bfd_link_relocatable (&link_info) && config.build_constructors)
++ return "ldscripts/${EMULATION_NAME}.xu";
++ else if (bfd_link_relocatable (&link_info))
++ return "ldscripts/${EMULATION_NAME}.xr";
++ else if (!config.text_read_only)
++ return "ldscripts/${EMULATION_NAME}.xbn";
++EOF
++if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then :
++else
++fragment <<EOF
++ else if (!config.magic_demand_paged)
++ return "ldscripts/${EMULATION_NAME}.xn";
++EOF
++fi
++if test -n "$GENERATE_PIE_SCRIPT" ; then
++if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
++fragment <<EOF
++ else if (bfd_link_pie (&link_info)
++ && link_info.combreloc
++ && link_info.relro
++ && (link_info.flags & DF_BIND_NOW))
++ return "ldscripts/${EMULATION_NAME}.xdw";
++ else if (bfd_link_pie (&link_info)
++ && link_info.combreloc)
++ return "ldscripts/${EMULATION_NAME}.xdc";
++EOF
++fi
++fragment <<EOF
++ else if (bfd_link_pie (&link_info))
++ return "ldscripts/${EMULATION_NAME}.xd";
++EOF
++fi
++if test -n "$GENERATE_COMBRELOC_SCRIPT" ; then
++fragment <<EOF
++ else if (link_info.combreloc && link_info.relro
++ && (link_info.flags & DF_BIND_NOW))
++ return "ldscripts/${EMULATION_NAME}.xw";
++ else if (link_info.combreloc)
++ return "ldscripts/${EMULATION_NAME}.xc";
++EOF
++fi
++fragment <<EOF
++ else
++ return "ldscripts/${EMULATION_NAME}.x";
++}
++
++EOF
++fi
++fi
++
++if test -n "$PARSE_AND_LIST_PROLOGUE" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_PROLOGUE
++EOF
++fi
++
++fragment <<EOF
++
++enum elf_options
++{
++ OPTION_DISABLE_NEW_DTAGS = 400,
++ OPTION_ENABLE_NEW_DTAGS,
++ OPTION_GROUP,
++ OPTION_EH_FRAME_HDR,
++ OPTION_NO_EH_FRAME_HDR,
++ OPTION_EXCLUDE_LIBS,
++ OPTION_HASH_STYLE,
++ OPTION_BUILD_ID,
++ OPTION_AUDIT,
++ OPTION_COMPRESS_DEBUG
++};
++
++static void
++gld${EMULATION_NAME}_add_options
++ (int ns, char **shortopts, int nl, struct option **longopts,
++ int nrl ATTRIBUTE_UNUSED, struct option **really_longopts ATTRIBUTE_UNUSED)
++{
++EOF
++if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
++fragment <<EOF
++ static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:P:";
++EOF
++else
++fragment <<EOF
++ static const char xtra_short[] = "${PARSE_AND_LIST_SHORTOPTS}z:";
++EOF
++fi
++fragment <<EOF
++ static const struct option xtra_long[] = {
++EOF
++if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
++fragment <<EOF
++ {"audit", required_argument, NULL, OPTION_AUDIT},
++ {"Bgroup", no_argument, NULL, OPTION_GROUP},
++EOF
++fi
++fragment <<EOF
++ {"build-id", optional_argument, NULL, OPTION_BUILD_ID},
++ {"compress-debug-sections", required_argument, NULL, OPTION_COMPRESS_DEBUG},
++EOF
++if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
++fragment <<EOF
++ {"depaudit", required_argument, NULL, 'P'},
++ {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS},
++ {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS},
++ {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR},
++ {"no-eh-frame-hdr", no_argument, NULL, OPTION_NO_EH_FRAME_HDR},
++ {"exclude-libs", required_argument, NULL, OPTION_EXCLUDE_LIBS},
++ {"hash-style", required_argument, NULL, OPTION_HASH_STYLE},
++EOF
++fi
++if test -n "$PARSE_AND_LIST_LONGOPTS" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_LONGOPTS
++EOF
++fi
++fragment <<EOF
++ {NULL, no_argument, NULL, 0}
++ };
++
++ *shortopts = (char *) xrealloc (*shortopts, ns + sizeof (xtra_short));
++ memcpy (*shortopts + ns, &xtra_short, sizeof (xtra_short));
++ *longopts = (struct option *)
++ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long));
++ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long));
++}
++
++#define DEFAULT_BUILD_ID_STYLE "sha1"
++
++static bool
++gld${EMULATION_NAME}_handle_option (int optc)
++{
++ switch (optc)
++ {
++ default:
++ return false;
++
++ case OPTION_BUILD_ID:
++ if (emit_note_gnu_build_id != NULL)
++ {
++ free ((char *) emit_note_gnu_build_id);
++ emit_note_gnu_build_id = NULL;
++ }
++ if (optarg == NULL)
++ optarg = DEFAULT_BUILD_ID_STYLE;
++ if (strcmp (optarg, "none"))
++ emit_note_gnu_build_id = xstrdup (optarg);
++ break;
++
++ case OPTION_COMPRESS_DEBUG:
++ if (strcasecmp (optarg, "none") == 0)
++ config.compress_debug = COMPRESS_DEBUG_NONE;
++ else if (strcasecmp (optarg, "zlib") == 0)
++ config.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
++ else if (strcasecmp (optarg, "zlib-gnu") == 0)
++ config.compress_debug = COMPRESS_DEBUG_GNU_ZLIB;
++ else if (strcasecmp (optarg, "zlib-gabi") == 0)
++ config.compress_debug = COMPRESS_DEBUG_GABI_ZLIB;
++ else
++ einfo (_("%P%F: invalid --compress-debug-sections option: \`%s'\n"),
++ optarg);
++ break;
++EOF
++
++if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
++fragment <<EOF
++ case OPTION_AUDIT:
++ gld${EMULATION_NAME}_append_to_separated_string (&audit, optarg);
++ break;
++
++ case 'P':
++ gld${EMULATION_NAME}_append_to_separated_string (&depaudit, optarg);
++ break;
++
++ case OPTION_DISABLE_NEW_DTAGS:
++ link_info.new_dtags = false;
++ break;
++
++ case OPTION_ENABLE_NEW_DTAGS:
++ link_info.new_dtags = true;
++ break;
++
++ case OPTION_EH_FRAME_HDR:
++ link_info.eh_frame_hdr_type = DWARF2_EH_HDR;
++ break;
++
++ case OPTION_NO_EH_FRAME_HDR:
++ link_info.eh_frame_hdr_type = 0;
++ break;
++
++ case OPTION_GROUP:
++ link_info.flags_1 |= (bfd_vma) DF_1_GROUP;
++ /* Groups must be self-contained. */
++ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
++ link_info.unresolved_syms_in_shared_libs = RM_DIAGNOSE;
++ break;
++
++ case OPTION_EXCLUDE_LIBS:
++ add_excluded_libs (optarg);
++ break;
++
++ case OPTION_HASH_STYLE:
++ link_info.emit_hash = false;
++ link_info.emit_gnu_hash = false;
++ if (strcmp (optarg, "sysv") == 0)
++ link_info.emit_hash = true;
++ else if (strcmp (optarg, "gnu") == 0)
++ link_info.emit_gnu_hash = true;
++ else if (strcmp (optarg, "both") == 0)
++ {
++ link_info.emit_hash = true;
++ link_info.emit_gnu_hash = true;
++ }
++ else
++ einfo (_("%P%F: invalid hash style \`%s'\n"), optarg);
++ break;
++
++EOF
++fi
++fragment <<EOF
++ case 'z':
++ if (strcmp (optarg, "defs") == 0)
++ link_info.unresolved_syms_in_objects = RM_DIAGNOSE;
++ else if (strcmp (optarg, "muldefs") == 0)
++ link_info.allow_multiple_definition = true;
++ else if (startswith (optarg, "max-page-size="))
++ {
++ char *end;
++
++ link_info.maxpagesize = strtoul (optarg + 14, &end, 0);
++ if (*end || (link_info.maxpagesize & (link_info.maxpagesize - 1)) != 0)
++ einfo (_("%P%F: invalid maxium page size \`%s'\n"),
++ optarg + 14);
++ }
++ else if (startswith (optarg, "common-page-size="))
++ {
++ char *end;
++ link_info.commonpagesize = strtoul (optarg + 17, &end, 0);
++ if (*end
++ || (link_info.commonpagesize & (link_info.commonpagesize - 1)) != 0)
++ einfo (_("%P%F: invalid common page size \`%s'\n"),
++ optarg + 17);
++ }
++ else if (startswith (optarg, "stack-size="))
++ {
++ char *end;
++ link_info.stacksize = strtoul (optarg + 11, &end, 0);
++ if (*end || link_info.stacksize < 0)
++ einfo (_("%P%F: invalid stack size \`%s'\n"), optarg + 11);
++ if (!link_info.stacksize)
++ /* Use -1 for explicit no-stack, because zero means
++ 'default'. */
++ link_info.stacksize = -1;
++ }
++ else if (strcmp (optarg, "execstack") == 0)
++ {
++ link_info.execstack = true;
++ link_info.noexecstack = false;
++ }
++ else if (strcmp (optarg, "noexecstack") == 0)
++ {
++ link_info.noexecstack = true;
++ link_info.execstack = false;
++ }
++EOF
++
++if test x"$GENERATE_SHLIB_SCRIPT" = xyes; then
++fragment <<EOF
++ else if (strcmp (optarg, "global") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_GLOBAL;
++ else if (strcmp (optarg, "initfirst") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_INITFIRST;
++ else if (strcmp (optarg, "interpose") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_INTERPOSE;
++ else if (strcmp (optarg, "loadfltr") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_LOADFLTR;
++ else if (strcmp (optarg, "nodefaultlib") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_NODEFLIB;
++ else if (strcmp (optarg, "nodelete") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_NODELETE;
++ else if (strcmp (optarg, "nodlopen") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_NOOPEN;
++ else if (strcmp (optarg, "nodump") == 0)
++ link_info.flags_1 |= (bfd_vma) DF_1_NODUMP;
++ else if (strcmp (optarg, "now") == 0)
++ {
++ link_info.flags |= (bfd_vma) DF_BIND_NOW;
++ link_info.flags_1 |= (bfd_vma) DF_1_NOW;
++ }
++ else if (strcmp (optarg, "lazy") == 0)
++ {
++ link_info.flags &= ~(bfd_vma) DF_BIND_NOW;
++ link_info.flags_1 &= ~(bfd_vma) DF_1_NOW;
++ }
++ else if (strcmp (optarg, "origin") == 0)
++ {
++ link_info.flags |= (bfd_vma) DF_ORIGIN;
++ link_info.flags_1 |= (bfd_vma) DF_1_ORIGIN;
++ }
++ else if (strcmp (optarg, "combreloc") == 0)
++ link_info.combreloc = true;
++ else if (strcmp (optarg, "nocombreloc") == 0)
++ link_info.combreloc = false;
++ else if (strcmp (optarg, "nocopyreloc") == 0)
++ link_info.nocopyreloc = true;
++ else if (strcmp (optarg, "relro") == 0)
++ link_info.relro = true;
++ else if (strcmp (optarg, "norelro") == 0)
++ link_info.relro = false;
++ else if (strcmp (optarg, "common") == 0)
++ link_info.elf_stt_common = elf_stt_common;
++ else if (strcmp (optarg, "nocommon") == 0)
++ link_info.elf_stt_common = no_elf_stt_common;
++ else if (strcmp (optarg, "text") == 0)
++ link_info.error_textrel = true;
++ else if (strcmp (optarg, "notext") == 0)
++ link_info.error_textrel = false;
++ else if (strcmp (optarg, "textoff") == 0)
++ link_info.error_textrel = false;
++EOF
++fi
++
++if test -n "$PARSE_AND_LIST_ARGS_CASE_Z" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_ARGS_CASE_Z
++EOF
++fi
++
++fragment <<EOF
++ else
++ einfo (_("%P: warning: -z %s ignored.\n"), optarg);
++ break;
++EOF
++
++if test -n "$PARSE_AND_LIST_ARGS_CASES" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_ARGS_CASES
++EOF
++fi
++
++fragment <<EOF
++ }
++
++ return true;
++}
++
++EOF
++
++if test x"$LDEMUL_LIST_OPTIONS" != xgld"$EMULATION_NAME"_list_options; then
++gld_list_options="gld${EMULATION_NAME}_list_options"
++if test -n "$PARSE_AND_LIST_OPTIONS"; then
++fragment <<EOF
++
++static void
++gld${EMULATION_NAME}_list_options (FILE * file)
++{
++EOF
++
++if test -n "$PARSE_AND_LIST_OPTIONS" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_OPTIONS
++EOF
++fi
++
++fragment <<EOF
++}
++EOF
++else
++ gld_list_options="NULL"
++fi
++
++if test -n "$PARSE_AND_LIST_EPILOGUE" ; then
++fragment <<EOF
++ $PARSE_AND_LIST_EPILOGUE
++EOF
++fi
++fi
++
++fragment <<EOF
++
++struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
++{
++ ${LDEMUL_BEFORE_PARSE-gld${EMULATION_NAME}_before_parse},
++ ${LDEMUL_SYSLIB-syslib_default},
++ ${LDEMUL_HLL-hll_default},
++ ${LDEMUL_AFTER_PARSE-gld${EMULATION_NAME}_after_parse},
++ ${LDEMUL_BEFORE_PLUGIN_ALL_SYMBOLS_READ-NULL},
++ ${LDEMUL_AFTER_OPEN-gld${EMULATION_NAME}_after_open},
++ ${LDEMUL_AFTER_CHECK_RELOCS-after_check_relocs_default},
++ ${LDEMUL_BEFORE_PLACE_ORPHANS-before_place_orphans_default},
++ ${LDEMUL_AFTER_ALLOCATION-gld${EMULATION_NAME}_after_allocation},
++ ${LDEMUL_SET_OUTPUT_ARCH-set_output_arch_default},
++ ${LDEMUL_CHOOSE_TARGET-ldemul_default_target},
++ ${LDEMUL_BEFORE_ALLOCATION-gld${EMULATION_NAME}_before_allocation},
++ ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script},
++ "${EMULATION_NAME}",
++ "${OUTPUT_FORMAT}",
++ ${LDEMUL_FINISH-finish_default},
++ ppc_after_open_output,
++ ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-NULL},
++ ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan},
++ ${LDEMUL_SET_SYMBOLS-gld${EMULATION_NAME}_set_symbols},
++ ${LDEMUL_PARSE_ARGS-gld${EMULATION_NAME}_parse_args},
++ gld${EMULATION_NAME}_add_options,
++ gld${EMULATION_NAME}_handle_option,
++ ${LDEMUL_UNRECOGNIZED_FILE-NULL},
++ ${LDEMUL_LIST_OPTIONS-${gld_list_options}},
++ ${LDEMUL_RECOGNIZED_FILE-NULL},
++ ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL},
++ ${LDEMUL_NEW_VERS_PATTERN-NULL},
++ ${LDEMUL_EXTRA_MAP_FILE_TEXT-NULL},
++ NULL, //${LDEMUL_EMIT_CTF_EARLY-NULL}, /* FIXME: We have no CTF support? https://lwn.net/Articles/795384/ */
++ NULL, //${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL},
++ NULL, //${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL},
++ ${LDEMUL_PRINT_SYMBOL-NULL},
++ ${LDEMUL_FIND_START_SYMBOL-NULL}
++};
++EOF
+diff -ruN binutils-2.45/ld/ldfile.c binutils-2.45_mos/ld/ldfile.c
+--- binutils-2.45/ld/ldfile.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/ldfile.c 2025-07-27 14:39:08.712060584 +0300
+@@ -276,6 +276,39 @@
+ }
+
+
++/* Flavour support. */
++
++static int flavors_cmp(const void *f1, const void *f2);
++
++static int n_flavors, flavors_len;
++static char **flavors;
++
++static int
++flavors_cmp (const void *f1, const void *f2)
++{
++ return strcmp (*(char **)f1, *(char **)f2);
++}
++
++void
++ldfile_sort_flavors (void)
++{
++ if (n_flavors > 1)
++ qsort ((void *) flavors, n_flavors, sizeof (char **), flavors_cmp);
++}
++
++void
++ldfile_add_flavor (const char *name)
++{
++ n_flavors++;
++ if (flavors)
++ flavors = (char **) xrealloc ((void *)flavors, n_flavors * sizeof (char *));
++ else
++ flavors = (char **) xmalloc (sizeof (char *));
++ flavors [n_flavors-1] = (char *) name;
++ flavors_len += strlen (name);
++}
++
++
+ /* Test whether a pathname, after canonicalization, is the same or a
+ sub-directory of the sysroot directory. */
+
+@@ -550,6 +585,7 @@
+ const char *lib,
+ const char *suffix)
+ {
++ char *flavor_dir = (char *) alloca (flavors_len + n_flavors + 1);
+ search_dirs_type *search;
+
+ /* If this is not an archive, try to open it in the current
+@@ -577,6 +613,7 @@
+ for (search = search_head; search != NULL; search = search->next)
+ {
+ char *string;
++ int i, count;
+
+ if (entry->flags.dynamic && !bfd_link_relocatable (&link_info))
+ {
+@@ -584,20 +621,30 @@
+ return true;
+ }
+
+- if (entry->flags.maybe_archive && !entry->flags.full_name_provided)
+- string = concat (search->name, slash, lib, entry->filename,
+- arch, suffix, (const char *) NULL);
+- else
+- string = concat (search->name, slash, entry->filename,
+- (const char *) 0);
+-
+- if (ldfile_try_open_bfd (string, entry))
++ for (count = n_flavors; count >= 0; count--)
+ {
+- entry->filename = string;
+- return true;
+- }
++ *flavor_dir = '\0';
++ for (i = 0; i < count; i++)
++ {
++ strcat (flavor_dir, flavors[i]);
++ strcat (flavor_dir, slash);
++ }
+
+- free (string);
++ if (entry->flags.maybe_archive && !entry->flags.full_name_provided)
++ string = concat (search->name, slash, flavor_dir, lib, entry->filename,
++ arch, suffix, (const char *) NULL);
++ else
++ string = concat (search->name, slash, flavor_dir, entry->filename,
++ (const char *) 0);
++
++ if (ldfile_try_open_bfd (string, entry))
++ {
++ entry->filename = string;
++ return true;
++ }
++
++ free (string);
++ }
+ }
+
+ return false;
+diff -ruN binutils-2.45/ld/ldfile.h binutils-2.45_mos/ld/ldfile.h
+--- binutils-2.45/ld/ldfile.h 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/ldfile.h 2025-07-27 14:39:08.712060584 +0300
+@@ -76,6 +76,9 @@
+ extern bool ldfile_open_file_search
+ (const char *arch, struct lang_input_statement_struct *,
+ const char *lib, const char *suffix);
++extern void ldfile_sort_flavors(void);
++extern void ldfile_add_flavor(const char *);
++
+
+ extern void ldfile_add_remap
+ (const char *, const char *);
+diff -ruN binutils-2.45/ld/ldmain.c binutils-2.45_mos/ld/ldmain.c
+--- binutils-2.45/ld/ldmain.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/ldmain.c 2025-07-27 14:39:08.712060584 +0300
+@@ -884,10 +884,14 @@
+
+ /* Print error messages for any missing symbols, for any warning
+ symbols, and possibly multiple definitions. */
++#ifdef MORPHOS_TARGET
++ link_info.output_bfd->flags &= ~EXEC_P;
++#else
+ if (bfd_link_relocatable (&link_info))
+ link_info.output_bfd->flags &= ~EXEC_P;
+ else
+ link_info.output_bfd->flags |= EXEC_P;
++#endif
+
+ flagword flags = 0;
+ switch (config.compress_debug)
+@@ -1482,6 +1486,16 @@
+ && nval == oval)
+ return;
+
++#ifdef MORPHOS_TARGET
++ /* fm: let's check for the GCC4/5 defsym'd __abox__ symbol here and let
++ any redefinition in an object file section pass ... */
++ if (!strcmp(h->root.string,"__abox__") &&
++ h->type == bfd_link_hash_defined
++ && bfd_is_abs_section (osec))
++ return;
++#endif
++
++
+ /* If either section has the output_section field set to
+ bfd_abs_section_ptr, it means that the section is being
+ discarded, and this is not really a multiple definition at all.
+diff -ruN binutils-2.45/ld/lexsup.c binutils-2.45_mos/ld/lexsup.c
+--- binutils-2.45/ld/lexsup.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/lexsup.c 2025-07-27 14:39:08.712060584 +0300
+@@ -812,9 +812,14 @@
+ && optc != argv[last_optind][1])
+ {
+ if (optarg)
++#ifdef MORPHOS_TARGET
++ einfo (_("%P: Warning: unable to disambiguate: %s (did you mean -%s ?)\n"),
++ argv[last_optind], argv[last_optind]);
++#else
+ fatal (_("%P: Error: unable to disambiguate: "
+ "%s (did you mean -%s ?)\n"),
+ argv[last_optind], argv[last_optind]);
++#endif
+ else
+ einfo (_("%P: Warning: grouped short command line options are deprecated: %s\n"), argv[last_optind]);
+ }
+diff -ruN binutils-2.45/ld/Makefile.am binutils-2.45_mos/ld/Makefile.am
+--- binutils-2.45/ld/Makefile.am 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/Makefile.am 2025-07-27 14:39:08.712060584 +0300
+@@ -324,6 +324,8 @@
+ emcorepe.c \
+ emn10200.c \
+ emn10300.c \
++ emorphos.c \
++ emorphos_baserel.c \
+ emoxiebox.c \
+ emsp430X.c \
+ emsp430elf.c \
+diff -ruN binutils-2.45/ld/Makefile.in binutils-2.45_mos/ld/Makefile.in
+--- binutils-2.45/ld/Makefile.in 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/ld/Makefile.in 2025-07-27 14:39:08.712060584 +0300
+@@ -835,6 +835,8 @@
+ emcorepe.c \
+ emn10200.c \
+ emn10300.c \
++ emorphos.c \
++ emorphos_baserel.c \
+ emoxiebox.c \
+ emsp430X.c \
+ emsp430elf.c \
+@@ -1533,6 +1535,8 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10200.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emn10300.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emoxiebox.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emorphos.Po@am__quote@
++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emorphos_baserel.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430X.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/emsp430elf.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ends32belf.Po@am__quote@
+diff -ruN binutils-2.45/ld/scripttempl/morphos_baserel.sc binutils-2.45_mos/ld/scripttempl/morphos_baserel.sc
+--- binutils-2.45/ld/scripttempl/morphos_baserel.sc 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/ld/scripttempl/morphos_baserel.sc 2025-07-27 14:39:08.712060584 +0300
+@@ -0,0 +1,216 @@
++#
++# Unusual variables checked by this code:
++# NOP - two byte opcode for no-op (defaults to 0)
++# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
++# OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
++# (e.g., .PARISC.milli)
++# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
++# (e.g., .PARISC.global)
++# OTHER_SECTIONS - at the end
++# EXECUTABLE_SYMBOLS - symbols that must be defined for an
++# executable (e.g., _DYNAMIC_LINK)
++# TEXT_START_SYMBOLS - symbols that appear at the start of the
++# .text section.
++# DATA_START_SYMBOLS - symbols that appear at the start of the
++# .data section.
++# OTHER_BSS_SYMBOLS - symbols that appear at the start of the
++# .bss section besides __bss_start.
++#
++# When adding sections, do note that the names of some sections are used
++# when specifying the start address of the next.
++#
++test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
++test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
++test "$LD_FLAG" = "N" && DATA_ADDR=.
++SBSS2=".sbss2 ${RELOCATING-0} : { *(.sbss2) }"
++SDATA2=".sdata2 ${RELOCATING-0} : { *(.sdata2) }"
++INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
++PLT=".plt ${RELOCATING-0} : { *(.plt) }"
++cat <<EOF
++OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
++ "${LITTLE_OUTPUT_FORMAT}")
++OUTPUT_ARCH(${ARCH})
++
++${RELOCATING+ENTRY (__start)}
++${RELOCATING+${LIB_SEARCH_DIRS}}
++${RELOCATING+/* Do we need any of these for elf?
++ __DYNAMIC = 0; ${STACKZERO+${STACKZERO}} ${SHLIB_PATH+${SHLIB_PATH}} */}
++${RELOCATING+${EXECUTABLE_SYMBOLS}}
++${RELOCATING- /* For some reason, the Solaris linker makes bad executables
++ if gld -r is used and the intermediate file has sections starting
++ at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld
++ bug. But for now assigning the zero vmas works. */}
++
++${RELOCATING+PROVIDE (__stack = 0);}
++PROVIDE (__machtype = 0x1);
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ ${CREATE_SHLIB-${RELOCATING+. = ${TEXT_START_ADDR} + SIZEOF_HEADERS;}}
++ ${CREATE_SHLIB+${RELOCATING+. = SIZEOF_HEADERS;}}
++ ${CREATE_SHLIB-${INTERP}}
++ .hash ${RELOCATING-0} : { *(.hash) }
++ .dynsym ${RELOCATING-0} : { *(.dynsym) }
++ .dynstr ${RELOCATING-0} : { *(.dynstr) }
++ .gnu.version ${RELOCATING-0} : { *(.gnu.version) }
++ .gnu.version_d ${RELOCATING-0} : { *(.gnu.version_d) }
++ .gnu.version_r ${RELOCATING-0} : { *(.gnu.version_r) }
++ .rela.text ${RELOCATING-0} :
++ { *(.rela.text) *(.rela.gnu.linkonce.t*) }
++ .rela.got ${RELOCATING-0} : { *(.rela.got) }
++ .rela.got1 ${RELOCATING-0} : { *(.rela.got1) }
++ .rela.got2 ${RELOCATING-0} : { *(.rela.got2) }
++ .rela.ctors ${RELOCATING-0} : { *(.rela.ctors) }
++ .rela.dtors ${RELOCATING-0} : { *(.rela.dtors) }
++ .rela.init ${RELOCATING-0} : { *(.rela.init) }
++ .rela.fini ${RELOCATING-0} : { *(.rela.fini) }
++ .rela.plt ${RELOCATING-0} : { *(.rela.plt) }
++ .rela.rodata ${RELOCATING-0} :
++ { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
++ .rela.sdata ${RELOCATING-0} :
++ {
++ *(.rela.data)
++ *(.rela.gnu.linkonce.d*)
++ *(.rela.sdata)
++ }
++ .rela.sbss ${RELOCATING-0} :
++ {
++ *(.rela.sbss)
++ *(.rela.bss)
++ }
++ .rela.sdata2 ${RELOCATING-0} : { *(.rela.sdata2) }
++ .rela.sbss2 ${RELOCATING-0} : { *(.rela.sbss2) }
++ .text ${RELOCATING-0} :
++ {
++ PROVIDE (__text_start = .);
++ ${RELOCATING+${TEXT_START_SYMBOLS}}
++ *(.text)
++ *(.text.*)
++ KEEP(*(.eh_frame*))
++ /* .gnu.warning sections are handled specially by elf32.em. */
++ *(.gnu.warning)
++ *(.gnu.linkonce.t*)
++ PROVIDE (__text_end = .);
++ } =${NOP-0}
++ PROVIDE (__text_size = SIZEOF(.text));
++ .init ${RELOCATING-0} : { KEEP(*(.init)) } =${NOP-0}
++ .fini ${RELOCATING-0} : { KEEP(*(.fini)) } =${NOP-0}
++ .ctdt ${RELOCATING-0} : { KEEP(*(.ctdt)) } =${NOP-0}
++ ${RELOCATING+_etext = .;}
++ ${RELOCATING+PROVIDE (etext = .);}
++ ${CREATE_SHLIB-${SDATA2}}
++ ${CREATE_SHLIB-${SBSS2}}
++ ${RELOCATING+${OTHER_READONLY_SECTIONS}}
++
++ .got1 ${RELOCATING-0} : { *(.got1) }
++ .dynamic ${RELOCATING-0} : { *(.dynamic) }
++
++ /* Put .ctors and .dtors next to the .got2 section, so that the pointers
++ get relocated with -mrelocatable. Also put in the .fixup pointers.
++ The current compiler no longer needs this, but keep it around for 2.7.2 */
++
++ ${RELOCATING+PROVIDE (_GOT2_START_ = .);}
++ .got2 ${RELOCATING-0} : { *(.got2) }
++
++ ${RELOCATING+PROVIDE (__CTOR_LIST__ = .);}
++ .ctors ${RELOCATING-0} : { *(.ctors) }
++ ${RELOCATING+PROVIDE (__CTOR_END__ = .);}
++
++ ${RELOCATING+PROVIDE (__DTOR_LIST__ = .);}
++ .dtors ${RELOCATING-0} : { *(.dtors) }
++ ${RELOCATING+PROVIDE (__DTOR_END__ = .);}
++
++ ${RELOCATING+PROVIDE (_FIXUP_START_ = .);}
++ .fixup ${RELOCATING-0} : { *(.fixup) }
++ ${RELOCATING+PROVIDE (_FIXUP_END_ = .);}
++ ${RELOCATING+PROVIDE (_GOT2_END_ = .);}
++
++ ${RELOCATING+PROVIDE (_GOT_START_ = .);}
++ .got ${RELOCATING-0} : { *(.got) }
++ .got.plt ${RELOCATING-0} : { *(.got.plt) }
++ ${CREATE_SHLIB+${SDATA2}}
++ ${CREATE_SHLIB+${SBSS2}}
++ ${RELOCATING+PROVIDE (_GOT_END_ = .);}
++ .rodata ${RELOCATING-0} : { *(.rodata) }
++ /* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .sdata ${RELOCATING-0} :
++ {
++ /*PROVIDE (__sdata_start = .);*/
++ __sdata_start = .;
++ *(.data)
++ *(.data.*)
++ *(.data1)
++ *(.data1.*)
++ *(.data.rel)
++ *(.data.rel.local)
++ __small_start = .;
++ *(.sdata)
++ *(.sdata.*)
++ *(.gnu.linkonce.s.*)
++ ${CONSTRUCTING+CONSTRUCTORS}
++ PROVIDE (__r13_init = /*__small_start*/ __sdata_start + 0x8000);
++ PROVIDE (__sdata_end = .);
++ }
++ /*PROVIDE (__sdata_size = SIZEOF(.sdata));*/
++ ${RELOCATING+_edata = .;}
++ ${RELOCATING+PROVIDE (edata = .);}
++ .sbss ${RELOCATING-0} :
++ {
++ /*PROVIDE (__sbss_start = .);*/
++ __sbss_start = .;
++ *(.sbss)
++ *(.sbss.*)
++ *(.scommon)
++ *(.gnu.linkonce.sb.*)
++ *(.dynsbss)
++ *(.bss)
++ *(.bss.*)
++ *(.gnu.linkonce.b.*)
++ *(COMMON)
++ PROVIDE (__sbss_end = .);
++ }
++ PROVIDE (__sdata_size = __sbss_start - __sdata_start);
++ PROVIDE (__sbss_size = SIZEOF(.sbss));
++
++ /* These are needed for ELF backends which have not yet been
++ converted to the new style linker. */
++ .stab 0 : { *(.stab) }
++ .stabstr 0 : { *(.stabstr) }
++
++ /* DWARF debug sections.
++ Symbols in the DWARF debugging sections are relative to the beginning
++ of the section so we begin them at 0. */
++
++ /* DWARF 1 */
++ .debug 0 : { *(.debug) }
++ .line 0 : { *(.line) }
++
++ /* GNU DWARF 1 extensions */
++ .debug_srcinfo 0 : { *(.debug_srcinfo) }
++ .debug_sfnames 0 : { *(.debug_sfnames) }
++
++ /* DWARF 1.1 and DWARF 2 */
++ .debug_aranges 0 : { *(.debug_aranges) }
++ .debug_pubnames 0 : { *(.debug_pubnames) }
++
++ /* DWARF 2 */
++ .debug_info 0 : { *(.debug_info) }
++ .debug_abbrev 0 : { *(.debug_abbrev) }
++ .debug_line 0 : { *(.debug_line) }
++ .debug_frame 0 : { *(.debug_frame) }
++ .debug_str 0 : { *(.debug_str) }
++ .debug_loc 0 : { *(.debug_loc) }
++ .debug_macinfo 0 : { *(.debug_macinfo) }
++
++ /* SGI/MIPS DWARF 2 extensions */
++ .debug_weaknames 0 : { *(.debug_weaknames) }
++ .debug_funcnames 0 : { *(.debug_funcnames) }
++ .debug_typenames 0 : { *(.debug_typenames) }
++ .debug_varnames 0 : { *(.debug_varnames) }
++
++ /* These must appear regardless of ${RELOCATING}. */
++ ${OTHER_SECTIONS}
++}
++EOF
+diff -ruN binutils-2.45/ld/scripttempl/morphos.sc binutils-2.45_mos/ld/scripttempl/morphos.sc
+--- binutils-2.45/ld/scripttempl/morphos.sc 1970-01-01 02:00:00.000000000 +0200
++++ binutils-2.45_mos/ld/scripttempl/morphos.sc 2025-07-27 14:39:08.712060584 +0300
+@@ -0,0 +1,691 @@
++#
++# Unusual variables checked by this code:
++# NOP - four byte opcode for no-op (defaults to none)
++# NO_SMALL_DATA - no .sbss/.sbss2/.sdata/.sdata2 sections if not
++# empty.
++# SMALL_DATA_CTOR - .ctors contains small data.
++# SMALL_DATA_DTOR - .dtors contains small data.
++# DATA_ADDR - if end-of-text-plus-one-page isn't right for data start
++# INITIAL_READONLY_SECTIONS - at start of text segment
++# OTHER_READONLY_SECTIONS - other than .text .init .rodata ...
++# (e.g., .PARISC.milli)
++# OTHER_TEXT_SECTIONS - these get put in .text when relocating
++# OTHER_READWRITE_SECTIONS - other than .data .bss .ctors .sdata ...
++# (e.g., .PARISC.global)
++# OTHER_RELRO_SECTIONS - other than .data.rel.ro ...
++# (e.g. PPC32 .fixup, .got[12])
++# OTHER_BSS_SECTIONS - other than .bss .sbss ...
++# ATTRS_SECTIONS - at the end
++# OTHER_SECTIONS - at the end
++# EXECUTABLE_SYMBOLS - symbols that must be defined for an
++# executable (e.g., _DYNAMIC_LINK)
++# TEXT_START_ADDR - the first byte of the text segment, after any
++# headers.
++# TEXT_BASE_ADDRESS - the first byte of the text segment.
++# TEXT_START_SYMBOLS - symbols that appear at the start of the
++# .text section.
++# DATA_START_SYMBOLS - symbols that appear at the start of the
++# .data section.
++# DATA_END_SYMBOLS - symbols that appear at the end of the
++# writeable data sections.
++# OTHER_GOT_SYMBOLS - symbols defined just before .got.
++# OTHER_GOT_SECTIONS - sections just after .got.
++# OTHER_SDATA_SECTIONS - sections just after .sdata.
++# OTHER_BSS_SYMBOLS - symbols that appear at the start of the
++# .bss section besides __bss_start.
++# DATA_PLT - .plt should be in data segment, not text segment.
++# PLT_BEFORE_GOT - .plt just before .got when .plt is in data segement.
++# BSS_PLT - .plt should be in bss segment
++# NO_REL_RELOCS - Don't include .rel.* sections in script
++# NO_RELA_RELOCS - Don't include .rela.* sections in script
++# NON_ALLOC_DYN - Place dynamic sections after data segment.
++# TEXT_DYNAMIC - .dynamic in text segment, not data segment.
++# EMBEDDED - whether this is for an embedded system.
++# SHLIB_TEXT_START_ADDR - if set, add to SIZEOF_HEADERS to set
++# start address of shared library.
++# INPUT_FILES - INPUT command of files to always include
++# WRITABLE_RODATA - if set, the .rodata section should be writable
++# INIT_START, INIT_END - statements just before and just after
++# combination of .init sections.
++# FINI_START, FINI_END - statements just before and just after
++# combination of .fini sections.
++# STACK_ADDR - start of a .stack section.
++# OTHER_SYMBOLS - symbols to place right at the end of the script.
++# ETEXT_NAME - name of a symbol for the end of the text section,
++# normally etext.
++# SEPARATE_CODE - if set, .text and similar sections containing
++# actual machine instructions must be in wholly disjoint
++# pages from any other data, including headers
++# SEPARATE_GOTPLT - if set, .got.plt should be separate output section,
++# so that .got can be in the RELRO area. It should be set to
++# the number of bytes in the beginning of .got.plt which can be
++# in the RELRO area as well.
++# USER_LABEL_PREFIX - prefix to add to user-visible symbols.
++# RODATA_NAME, SDATA_NAME, SBSS_NAME, BSS_NAME - base parts of names
++# for standard sections, without initial "." or suffixes.
++#
++# When adding sections, do note that the names of some sections are used
++# when specifying the start address of the next.
++#
++
++# Many sections come in three flavours. There is the 'real' section,
++# like ".data". Then there are the per-procedure or per-variable
++# sections, generated by -ffunction-sections and -fdata-sections in GCC,
++# and useful for --gc-sections, which for a variable "foo" might be
++# ".data.foo". Then there are the linkonce sections, for which the linker
++# eliminates duplicates, which are named like ".gnu.linkonce.d.foo".
++# The exact correspondences are:
++#
++# Section Linkonce section
++# .text .gnu.linkonce.t.foo
++# .rodata .gnu.linkonce.r.foo
++# .data .gnu.linkonce.d.foo
++# .bss .gnu.linkonce.b.foo
++# .sdata .gnu.linkonce.s.foo
++# .sbss .gnu.linkonce.sb.foo
++# .sdata2 .gnu.linkonce.s2.foo
++# .sbss2 .gnu.linkonce.sb2.foo
++# .debug_info .gnu.linkonce.wi.foo
++# .tdata .gnu.linkonce.td.foo
++# .tbss .gnu.linkonce.tb.foo
++# .lrodata .gnu.linkonce.lr.foo
++# .ldata .gnu.linkonce.l.foo
++# .lbss .gnu.linkonce.lb.foo
++#
++# Each of these can also have corresponding .rel.* and .rela.* sections.
++
++if test -n "$NOP"; then
++ FILL="=$NOP"
++else
++ FILL=
++fi
++
++test -z "$RODATA_NAME" && RODATA_NAME=rodata
++test -z "$SDATA_NAME" && SDATA_NAME=sdata
++test -z "$SBSS_NAME" && SBSS_NAME=sbss
++test -z "$BSS_NAME" && BSS_NAME=bss
++test -z "${BIG_OUTPUT_FORMAT}" && BIG_OUTPUT_FORMAT=${OUTPUT_FORMAT}
++test -z "${LITTLE_OUTPUT_FORMAT}" && LITTLE_OUTPUT_FORMAT=${OUTPUT_FORMAT}
++if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHINE}; fi
++test -z "${ELFSIZE}" && ELFSIZE=32
++test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
++test "$LD_FLAG" = "N" && DATA_ADDR=.
++test -z "${ETEXT_NAME}" && ETEXT_NAME=${USER_LABEL_PREFIX}etext
++test -n "$CREATE_SHLIB$CREATE_PIE" && test -n "$SHLIB_DATA_ADDR" && COMMONPAGESIZE=""
++test -z "$CREATE_SHLIB$CREATE_PIE" && test -n "$DATA_ADDR" && COMMONPAGESIZE=""
++test -n "$RELRO_NOW" && unset SEPARATE_GOTPLT
++test -z "$ATTRS_SECTIONS" && ATTRS_SECTIONS=".gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }"
++DATA_SEGMENT_ALIGN="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
++DATA_SEGMENT_RELRO_END=""
++DATA_SEGMENT_END=""
++if test -n "${COMMONPAGESIZE}"; then
++ DATA_SEGMENT_ALIGN="ALIGN (${SEGMENT_SIZE}) - ((${MAXPAGESIZE} - .) & (${MAXPAGESIZE} - 1)); . = DATA_SEGMENT_ALIGN (${MAXPAGESIZE}, ${COMMONPAGESIZE})"
++ DATA_SEGMENT_END=". = DATA_SEGMENT_END (.);"
++ DATA_SEGMENT_RELRO_END=". = DATA_SEGMENT_RELRO_END (${SEPARATE_GOTPLT-0}, .);"
++fi
++if test -z "${INITIAL_READONLY_SECTIONS}${CREATE_SHLIB}"; then
++ INITIAL_READONLY_SECTIONS=".interp ${RELOCATING-0} : { *(.interp) }"
++fi
++if test -z "$PLT"; then
++ IPLT=".iplt ${RELOCATING-0} : { *(.iplt) }"
++ PLT=".plt ${RELOCATING-0} : { *(.plt)${IREL_IN_PLT+ *(.iplt)} }
++ ${IREL_IN_PLT-$IPLT}"
++fi
++test -n "${DATA_PLT-${BSS_PLT-text}}" && TEXT_PLT=yes
++if test -z "$GOT"; then
++ if test -z "$SEPARATE_GOTPLT"; then
++ GOT=".got ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }"
++ else
++ GOT=".got ${RELOCATING-0} : { *(.got) *(.igot) }"
++ GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) *(.igot.plt) }"
++ fi
++fi
++REL_IFUNC=".rel.ifunc ${RELOCATING-0} : { *(.rel.ifunc) }"
++RELA_IFUNC=".rela.ifunc ${RELOCATING-0} : { *(.rela.ifunc) }"
++REL_IPLT=".rel.iplt ${RELOCATING-0} :
++ {
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_start = .);}}
++ *(.rel.iplt)
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_end = .);}}
++ }"
++RELA_IPLT=".rela.iplt ${RELOCATING-0} :
++ {
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_start = .);}}
++ *(.rela.iplt)
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_end = .);}}
++ }"
++DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
++RODATA=".${RODATA_NAME} ${RELOCATING-0} : { *(.${RODATA_NAME}${RELOCATING+ .${RODATA_NAME}.* .gnu.linkonce.r.*}) }"
++DATARELRO=".data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }"
++DISCARDED="/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }"
++if test -z "${NO_SMALL_DATA}"; then
++ SBSS=".${SBSS_NAME} ${RELOCATING-0} :
++ {
++ PROVIDE (__sbss_start = .);
++ ${CREATE_SHLIB+*(.${SBSS_NAME}2 .${SBSS_NAME}2.* .gnu.linkonce.sb2.*)}
++ *(.dyn${SBSS_NAME})
++ *(.${SBSS_NAME}${RELOCATING+ .${SBSS_NAME}.* .gnu.linkonce.sb.*})
++ *(.scommon)
++ PROVIDE (__sbss_end = .);
++ }
++ PROVIDE (__sbss_size = SIZEOF(.sbss));"
++ SBSS2=".${SBSS_NAME}2 ${RELOCATING-0} : { *(.${SBSS_NAME}2${RELOCATING+ .${SBSS_NAME}2.* .gnu.linkonce.sb2.*}) }"
++ SDATA="/* We want the small data sections together, so single-instruction offsets
++ can access them all, and initialized data all before uninitialized, so
++ we can shorten the on-disk segment size. */
++ .${SDATA_NAME} ${RELOCATING-0} :
++ {
++ PROVIDE (__sdata_start = .);
++ ${RELOCATING+${SDATA_START_SYMBOLS}}
++ ${CREATE_SHLIB+*(.${SDATA_NAME}2 .${SDATA_NAME}2.* .gnu.linkonce.s2.*)}
++ *(.${SDATA_NAME}${RELOCATING+ .${SDATA_NAME}.* .gnu.linkonce.s.*})
++ PROVIDE (__r13_init = 0x8000);
++ PROVIDE (__sdata_end = .);
++ }
++ PROVIDE (__sdata_size = SIZEOF(.sdata));"
++ SDATA2=".${SDATA_NAME}2 ${RELOCATING-0} :
++ {
++ ${RELOCATING+${SDATA2_START_SYMBOLS}}
++ *(.${SDATA_NAME}2${RELOCATING+ .${SDATA_NAME}2.* .gnu.linkonce.s2.*})
++ }"
++ REL_SDATA=".rel.${SDATA_NAME} ${RELOCATING-0} : { *(.rel.${SDATA_NAME}${RELOCATING+ .rel.${SDATA_NAME}.* .rel.gnu.linkonce.s.*}) }
++ .rela.${SDATA_NAME} ${RELOCATING-0} : { *(.rela.${SDATA_NAME}${RELOCATING+ .rela.${SDATA_NAME}.* .rela.gnu.linkonce.s.*}) }"
++ REL_SBSS=".rel.${SBSS_NAME} ${RELOCATING-0} : { *(.rel.${SBSS_NAME}${RELOCATING+ .rel.${SBSS_NAME}.* .rel.gnu.linkonce.sb.*}) }
++ .rela.${SBSS_NAME} ${RELOCATING-0} : { *(.rela.${SBSS_NAME}${RELOCATING+ .rela.${SBSS_NAME}.* .rela.gnu.linkonce.sb.*}) }"
++ REL_SDATA2=".rel.${SDATA_NAME}2 ${RELOCATING-0} : { *(.rel.${SDATA_NAME}2${RELOCATING+ .rel.${SDATA_NAME}2.* .rel.gnu.linkonce.s2.*}) }
++ .rela.${SDATA_NAME}2 ${RELOCATING-0} : { *(.rela.${SDATA_NAME}2${RELOCATING+ .rela.${SDATA_NAME}2.* .rela.gnu.linkonce.s2.*}) }"
++ REL_SBSS2=".rel.${SBSS_NAME}2 ${RELOCATING-0} : { *(.rel.${SBSS_NAME}2${RELOCATING+ .rel.${SBSS_NAME}2.* .rel.gnu.linkonce.sb2.*}) }
++ .rela.${SBSS_NAME}2 ${RELOCATING-0} : { *(.rela.${SBSS_NAME}2${RELOCATING+ .rela.${SBSS_NAME}2.* .rela.gnu.linkonce.sb2.*}) }"
++else
++ NO_SMALL_DATA=" "
++fi
++if test -z "${DATA_GOT}"; then
++ if test -n "${NO_SMALL_DATA}"; then
++ DATA_GOT=" "
++ fi
++fi
++if test -z "${SDATA_GOT}"; then
++ if test -z "${NO_SMALL_DATA}"; then
++ SDATA_GOT=" "
++ fi
++fi
++test -n "$SEPARATE_GOTPLT" && SEPARATE_GOTPLT=" "
++test "${LARGE_SECTIONS}" = "yes" && REL_LARGE="
++ .rel.ldata ${RELOCATING-0} : { *(.rel.ldata${RELOCATING+ .rel.ldata.* .rel.gnu.linkonce.l.*}) }
++ .rela.ldata ${RELOCATING-0} : { *(.rela.ldata${RELOCATING+ .rela.ldata.* .rela.gnu.linkonce.l.*}) }
++ .rel.lbss ${RELOCATING-0} : { *(.rel.lbss${RELOCATING+ .rel.lbss.* .rel.gnu.linkonce.lb.*}) }
++ .rela.lbss ${RELOCATING-0} : { *(.rela.lbss${RELOCATING+ .rela.lbss.* .rela.gnu.linkonce.lb.*}) }
++ .rel.lrodata ${RELOCATING-0} : { *(.rel.lrodata${RELOCATING+ .rel.lrodata.* .rel.gnu.linkonce.lr.*}) }
++ .rela.lrodata ${RELOCATING-0} : { *(.rela.lrodata${RELOCATING+ .rela.lrodata.* .rela.gnu.linkonce.lr.*}) }"
++test "${LARGE_SECTIONS}" = "yes" && OTHER_BSS_SECTIONS="
++ ${OTHER_BSS_SECTIONS}
++ .lbss ${RELOCATING-0} :
++ {
++ *(.dynlbss)
++ *(.lbss${RELOCATING+ .lbss.* .gnu.linkonce.lb.*})
++ *(LARGE_COMMON)
++ }"
++test "${LARGE_SECTIONS}" = "yes" && LARGE_SECTIONS="
++ .lrodata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} :
++ {
++ *(.lrodata${RELOCATING+ .lrodata.* .gnu.linkonce.lr.*})
++ }
++ .ldata ${RELOCATING-0} ${RELOCATING+ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))} :
++ {
++ *(.ldata${RELOCATING+ .ldata.* .gnu.linkonce.l.*})
++ ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
++ }"
++if test "${ENABLE_INITFINI_ARRAY}" = "yes"; then
++ SORT_INIT_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))"
++ SORT_FINI_ARRAY="KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))"
++ CTORS_IN_INIT_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors))"
++ DTORS_IN_FINI_ARRAY="KEEP (*(EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .dtors))"
++else
++ SORT_INIT_ARRAY="KEEP (*(SORT(.init_array.*)))"
++ SORT_FINI_ARRAY="KEEP (*(SORT(.fini_array.*)))"
++ CTORS_IN_INIT_ARRAY=
++ DTORS_IN_FINI_ARRAY=
++fi
++INIT_ARRAY=".init_array ${RELOCATING-0} :
++ {
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_start = .);}}
++ ${SORT_INIT_ARRAY}
++ KEEP (*(.init_array))
++ ${CTORS_IN_INIT_ARRAY}
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__init_array_end = .);}}
++ }"
++FINI_ARRAY=".fini_array ${RELOCATING-0} :
++ {
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_start = .);}}
++ ${SORT_FINI_ARRAY}
++ KEEP (*(.fini_array))
++ ${DTORS_IN_FINI_ARRAY}
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__fini_array_end = .);}}
++ }"
++CTOR=".ctors ${CONSTRUCTING-0} :
++ {
++ ${CONSTRUCTING+${CTOR_START}}
++ /* gcc uses crtbegin.o to find the start of
++ the constructors, so we make sure it is
++ first. Because this is a wildcard, it
++ doesn't matter if the user does not
++ actually link against crtbegin.o; the
++ linker won't look for a file to match a
++ wildcard. The wildcard also means that it
++ doesn't matter which directory crtbegin.o
++ is in. */
++
++ KEEP (*crtbegin.o(.ctors))
++ KEEP (*crtbegin?.o(.ctors))
++
++ /* We don't want to include the .ctor section from
++ the crtend.o file until after the sorted ctors.
++ The .ctor section from the crtend file contains the
++ end of ctors marker and it must be last */
++
++ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .ctors))
++ KEEP (*(SORT(.ctors.*)))
++ KEEP (*(.ctors))
++ ${CONSTRUCTING+${CTOR_END}}
++ }"
++DTOR=".dtors ${CONSTRUCTING-0} :
++ {
++ ${CONSTRUCTING+${DTOR_START}}
++ KEEP (*crtbegin.o(.dtors))
++ KEEP (*crtbegin?.o(.dtors))
++ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o $OTHER_EXCLUDE_FILES) .dtors))
++ KEEP (*(SORT(.dtors.*)))
++ KEEP (*(.dtors))
++ ${CONSTRUCTING+${DTOR_END}}
++ }"
++STACK=" .stack ${RELOCATING-0}${RELOCATING+${STACK_ADDR}} :
++ {
++ ${RELOCATING+${USER_LABEL_PREFIX}_stack = .;}
++ *(.stack)
++ }"
++
++TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${TEXT_START_ADDR})"
++SHLIB_TEXT_START_ADDR="SEGMENT_START(\"text-segment\", ${SHLIB_TEXT_START_ADDR:-0})"
++
++if [ -z "$SEPARATE_CODE" ]; then
++ SIZEOF_HEADERS_CODE=" + SIZEOF_HEADERS"
++else
++ SIZEOF_HEADERS_CODE=
++fi
++
++# if this is for an embedded system, don't add SIZEOF_HEADERS.
++if [ -z "$EMBEDDED" ]; then
++ test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}${SIZEOF_HEADERS_CODE}"
++else
++ test -z "${TEXT_BASE_ADDRESS}" && TEXT_BASE_ADDRESS="${TEXT_START_ADDR}"
++fi
++
++cat <<EOF
++OUTPUT_FORMAT("${OUTPUT_FORMAT}", "${BIG_OUTPUT_FORMAT}",
++ "${LITTLE_OUTPUT_FORMAT}")
++OUTPUT_ARCH(${OUTPUT_ARCH})
++
++${RELOCATING+ENTRY (__start)}
++${RELOCATING+${LIB_SEARCH_DIRS}}
++${RELOCATING+${EXECUTABLE_SYMBOLS}}
++${RELOCATING+${INPUT_FILES}}
++${RELOCATING- /* For some reason, the Solaris linker makes bad executables
++ if gld -r is used and the intermediate file has sections starting
++ at non-zero addresses. Could be a Solaris ld bug, could be a GNU ld
++ bug. But for now assigning the zero vmas works. */}
++
++${RELOCATING+PROVIDE (__stack = 0);}
++PROVIDE (__machtype = 0x1);
++SECTIONS
++{
++ /* Read-only sections, merged into text segment: */
++ ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+PROVIDE (__executable_start = ${TEXT_START_ADDR}); . = ${TEXT_BASE_ADDRESS};}}}
++ ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
++ ${CREATE_PIE+${RELOCATING+. = ${SHLIB_TEXT_START_ADDR}${SIZEOF_HEADERS_CODE};}}
++EOF
++
++emit_early_ro()
++{
++ cat <<EOF
++ ${INITIAL_READONLY_SECTIONS}
++ .note.gnu.build-id : { *(.note.gnu.build-id) }
++EOF
++}
++
++test -n "${SEPARATE_CODE}" || emit_early_ro
++
++test -n "${RELOCATING+0}" || unset NON_ALLOC_DYN
++test -z "${NON_ALLOC_DYN}" || TEXT_DYNAMIC=
++cat > ldscripts/dyntmp.$$ <<EOF
++ ${TEXT_DYNAMIC+${DYNAMIC}}
++ .hash ${RELOCATING-0} : { *(.hash) }
++ .gnu.hash ${RELOCATING-0} : { *(.gnu.hash) }
++ .dynsym ${RELOCATING-0} : { *(.dynsym) }
++ .dynstr ${RELOCATING-0} : { *(.dynstr) }
++ .gnu.version ${RELOCATING-0} : { *(.gnu.version) }
++ .gnu.version_d ${RELOCATING-0}: { *(.gnu.version_d) }
++ .gnu.version_r ${RELOCATING-0}: { *(.gnu.version_r) }
++EOF
++
++if [ "x$COMBRELOC" = x ]; then
++ COMBRELOCCAT="cat >> ldscripts/dyntmp.$$"
++else
++ COMBRELOCCAT="cat > $COMBRELOC"
++fi
++eval $COMBRELOCCAT <<EOF
++ ${INITIAL_RELOC_SECTIONS}
++ .rel.text ${RELOCATING-0} : { *(.rel.text${RELOCATING+ .rel.text.* .rel.gnu.linkonce.t.*}) }
++ .rela.text ${RELOCATING-0} : { *(.rela.text${RELOCATING+ .rela.text.* .rela.gnu.linkonce.t.*}) }
++ .rel.init ${RELOCATING-0} : { *(.rel.init) }
++ .rela.init ${RELOCATING-0} : { *(.rela.init) }
++ .rel.fini ${RELOCATING-0} : { *(.rel.fini) }
++ .rela.fini ${RELOCATING-0} : { *(.rela.fini) }
++ .rel.${RODATA_NAME} ${RELOCATING-0} : { *(.rel.${RODATA_NAME}${RELOCATING+ .rel.${RODATA_NAME}.* .rel.gnu.linkonce.r.*}) }
++ .rela.${RODATA_NAME} ${RELOCATING-0} : { *(.rela.${RODATA_NAME}${RELOCATING+ .rela.${RODATA_NAME}.* .rela.gnu.linkonce.r.*}) }
++ ${OTHER_READONLY_RELOC_SECTIONS}
++ .rel.data.rel.ro ${RELOCATING-0} : { *(.rel.data.rel.ro${RELOCATING+ .rel.data.rel.ro.* .rel.gnu.linkonce.d.rel.ro.*}) }
++ .rela.data.rel.ro ${RELOCATING-0} : { *(.rela.data.rel.ro${RELOCATING+ .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*}) }
++ .rel.data ${RELOCATING-0} : { *(.rel.data${RELOCATING+ .rel.data.* .rel.gnu.linkonce.d.*}) }
++ .rela.data ${RELOCATING-0} : { *(.rela.data${RELOCATING+ .rela.data.* .rela.gnu.linkonce.d.*}) }
++ ${OTHER_READWRITE_RELOC_SECTIONS}
++ .rel.tdata ${RELOCATING-0} : { *(.rel.tdata${RELOCATING+ .rel.tdata.* .rel.gnu.linkonce.td.*}) }
++ .rela.tdata ${RELOCATING-0} : { *(.rela.tdata${RELOCATING+ .rela.tdata.* .rela.gnu.linkonce.td.*}) }
++ .rel.tbss ${RELOCATING-0} : { *(.rel.tbss${RELOCATING+ .rel.tbss.* .rel.gnu.linkonce.tb.*}) }
++ .rela.tbss ${RELOCATING-0} : { *(.rela.tbss${RELOCATING+ .rela.tbss.* .rela.gnu.linkonce.tb.*}) }
++ .rel.ctors ${RELOCATING-0} : { *(.rel.ctors) }
++ .rela.ctors ${RELOCATING-0} : { *(.rela.ctors) }
++ .rel.dtors ${RELOCATING-0} : { *(.rel.dtors) }
++ .rela.dtors ${RELOCATING-0} : { *(.rela.dtors) }
++ .rel.got ${RELOCATING-0} : { *(.rel.got) }
++ .rela.got ${RELOCATING-0} : { *(.rela.got) }
++ ${OTHER_GOT_RELOC_SECTIONS}
++ ${REL_SDATA}
++ ${REL_SBSS}
++ ${REL_SDATA2}
++ ${REL_SBSS2}
++ .rel.${BSS_NAME} ${RELOCATING-0} : { *(.rel.${BSS_NAME}${RELOCATING+ .rel.${BSS_NAME}.* .rel.gnu.linkonce.b.*}) }
++ .rela.${BSS_NAME} ${RELOCATING-0} : { *(.rela.${BSS_NAME}${RELOCATING+ .rela.${BSS_NAME}.* .rela.gnu.linkonce.b.*}) }
++ ${REL_LARGE}
++ ${IREL_IN_PLT+$REL_IFUNC}
++ ${IREL_IN_PLT+$RELA_IFUNC}
++ ${IREL_IN_PLT-$REL_IPLT}
++ ${IREL_IN_PLT-$RELA_IPLT}
++EOF
++
++if [ -n "$COMBRELOC" ]; then
++cat >> ldscripts/dyntmp.$$ <<EOF
++ .rel.dyn ${RELOCATING-0} :
++ {
++EOF
++sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rela\./d;s/^.*: { *\(.*\)}$/ \1/' $COMBRELOC >> ldscripts/dyntmp.$$
++cat >> ldscripts/dyntmp.$$ <<EOF
++ }
++ .rela.dyn ${RELOCATING-0} :
++ {
++EOF
++sed -e '/^[ ]*[{}][ ]*$/d;/:[ ]*$/d;/\.rel\./d;s/^.*: { *\(.*\)}/ \1/' $COMBRELOC >> ldscripts/dyntmp.$$
++cat >> ldscripts/dyntmp.$$ <<EOF
++ }
++EOF
++fi
++
++cat >> ldscripts/dyntmp.$$ <<EOF
++ .rel.plt ${RELOCATING-0} :
++ {
++ *(.rel.plt)
++ ${IREL_IN_PLT+${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_start = .);}}}
++ ${IREL_IN_PLT+${RELOCATING+*(.rel.iplt)}}
++ ${IREL_IN_PLT+${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rel_iplt_end = .);}}}
++ }
++ .rela.plt ${RELOCATING-0} :
++ {
++ *(.rela.plt)
++ ${IREL_IN_PLT+${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_start = .);}}}
++ ${IREL_IN_PLT+${RELOCATING+*(.rela.iplt)}}
++ ${IREL_IN_PLT+${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__rela_iplt_end = .);}}}
++ }
++ ${OTHER_PLT_RELOC_SECTIONS}
++EOF
++
++emit_dyn()
++{
++ if test -z "${NO_REL_RELOCS}${NO_RELA_RELOCS}"; then
++ cat ldscripts/dyntmp.$$
++ else
++ if test -z "${NO_REL_RELOCS}"; then
++ sed -e '/^[ ]*\.rela\.[^}]*$/,/}/d' -e '/^[ ]*\.rela\./d' ldscripts/dyntmp.$$
++ fi
++ if test -z "${NO_RELA_RELOCS}"; then
++ sed -e '/^[ ]*\.rel\.[^}]*$/,/}/d' -e '/^[ ]*\.rel\./d' ldscripts/dyntmp.$$
++ fi
++ fi
++ rm -f ldscripts/dyntmp.$$
++}
++
++test -n "${NON_ALLOC_DYN}${SEPARATE_CODE}" || emit_dyn
++
++cat <<EOF
++
++ ${TEXT_PLT+${PLT}}
++ ${TINY_READONLY_SECTION}
++ .text ${RELOCATING-0} :
++ {
++ PROVIDE (__text_start = .);
++ ${RELOCATING+${TEXT_START_SYMBOLS}}
++ *(.text)
++ *(.text.*)
++ KEEP(*(.eh_frame*))
++ *(.text .stub${RELOCATING+ .text.* .gnu.linkonce.t.*})
++ /* .gnu.warning sections are handled specially by elf32.em. */
++ *(.gnu.warning)
++ PROVIDE (__text_end = .);
++ } =${NOP-0}
++ PROVIDE (__text_size = SIZEOF(.text));
++
++ .init ${RELOCATING-0} :
++ {
++ ${RELOCATING+${INIT_START}}
++ KEEP (*(SORT_NONE(.init)))
++ ${RELOCATING+${INIT_END}}
++ } ${FILL}
++
++ .fini ${RELOCATING-0} :
++ {
++ ${RELOCATING+${FINI_START}}
++ KEEP (*(SORT_NONE(.fini)))
++ ${RELOCATING+${FINI_END}}
++ } ${FILL}
++ .ctdt ${RELOCATING-0} : { KEEP(*(.ctdt)) } =${NOP-0}
++ ${RELOCATING+PROVIDE (__${ETEXT_NAME} = .);}
++ ${RELOCATING+PROVIDE (_${ETEXT_NAME} = .);}
++ ${RELOCATING+PROVIDE (${ETEXT_NAME} = .);}
++EOF
++
++if test -n "${SEPARATE_CODE}"; then
++ if test -n "${RODATA_ADDR}"; then
++ RODATA_ADDR="\
++SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR}) + SIZEOF_HEADERS"
++ else
++ RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))}"
++ RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${RODATA_ADDR})"
++ fi
++ if test -n "${SHLIB_RODATA_ADDR}"; then
++ SHLIB_RODATA_ADDR="\
++SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR}) + SIZEOF_HEADERS"
++ else
++ SHLIB_RODATA_ADDR="SEGMENT_START(\"rodata-segment\", ${SHLIB_RODATA_ADDR})"
++ SHLIB_RODATA_ADDR="ALIGN(${SEGMENT_SIZE}) + (. & (${MAXPAGESIZE} - 1))"
++ fi
++ cat <<EOF
++ /* Adjust the address for the rodata segment. We want to adjust up to
++ the same address within the page on the next page up. */
++ ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${RODATA_ADDR};}}}
++ ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_RODATA_ADDR};}}
++ ${CREATE_PIE+${RELOCATING+. = ${SHLIB_RODATA_ADDR};}}
++EOF
++ emit_early_ro
++ emit_dyn
++fi
++
++cat <<EOF
++ ${WRITABLE_RODATA-${RODATA}}
++ .${RODATA_NAME}1 ${RELOCATING-0} : { *(.${RODATA_NAME}1) }
++ ${CREATE_SHLIB-${SDATA2}}
++ ${CREATE_SHLIB-${SBSS2}}
++ ${OTHER_READONLY_SECTIONS}
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RO { *(.gcc_except_table
++ .gcc_except_table.*) }
++ /* These sections are generated by the Sun/Oracle C++ compiler. */
++ .exception_ranges ${RELOCATING-0} : ONLY_IF_RO { *(.exception_ranges
++ .exception_ranges*) }
++
++ /* Adjust the address for the data segment. We want to adjust up to
++ the same address within the page on the next page up. */
++ ${CREATE_SHLIB-${CREATE_PIE-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}}
++ ${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
++ ${CREATE_PIE+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
++
++ /* Exception handling */
++ .gcc_except_table ${RELOCATING-0} : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
++ .exception_ranges ${RELOCATING-0} : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
++
++ /* Thread Local Storage sections */
++ .tdata ${RELOCATING-0} : { *(.tdata${RELOCATING+ .tdata.* .gnu.linkonce.td.*}) }
++ .tbss ${RELOCATING-0} : { *(.tbss${RELOCATING+ .tbss.* .gnu.linkonce.tb.*})${RELOCATING+ *(.tcommon)} }
++
++ .preinit_array ${RELOCATING-0} :
++ {
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__preinit_array_start = .);}}
++ KEEP (*(.preinit_array))
++ ${RELOCATING+${CREATE_SHLIB-PROVIDE_HIDDEN (${USER_LABEL_PREFIX}__preinit_array_end = .);}}
++ }
++ ${RELOCATING+${INIT_ARRAY}}
++ ${RELOCATING+${FINI_ARRAY}}
++ ${SMALL_DATA_CTOR-${RELOCATING+${CTOR}}}
++ ${SMALL_DATA_DTOR-${RELOCATING+${DTOR}}}
++ .jcr ${RELOCATING-0} : { KEEP (*(.jcr)) }
++
++ ${RELOCATING+${DATARELRO}}
++ ${OTHER_RELRO_SECTIONS}
++ ${TEXT_DYNAMIC-${DYNAMIC}}
++ ${DATA_GOT+${RELRO_NOW+${GOT}}}
++ ${DATA_GOT+${RELRO_NOW+${GOTPLT}}}
++ ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT+${GOT}}}}
++ ${RELOCATING+${DATA_SEGMENT_RELRO_END}}
++ ${DATA_GOT+${RELRO_NOW-${SEPARATE_GOTPLT-${GOT}}}}
++ ${DATA_GOT+${RELRO_NOW-${GOTPLT}}}
++
++ ${DATA_PLT+${PLT_BEFORE_GOT-${PLT}}}
++
++ .data ${RELOCATING-0} :
++ {
++ PROVIDE (__data_start = .);
++ ${RELOCATING+${DATA_START_SYMBOLS}}
++ *(.data${RELOCATING+ .data.* .gnu.linkonce.d.*})
++ ${CONSTRUCTING+SORT(CONSTRUCTORS)}
++ PROVIDE (__data_end = .);
++ }
++ PROVIDE (__data_size = SIZEOF(.data));
++ .data1 ${RELOCATING-0} : { *(.data1) }
++ ${WRITABLE_RODATA+${RODATA}}
++ ${OTHER_READWRITE_SECTIONS}
++ ${SMALL_DATA_CTOR+${RELOCATING+${CTOR}}}
++ ${SMALL_DATA_DTOR+${RELOCATING+${DTOR}}}
++ ${DATA_PLT+${PLT_BEFORE_GOT+${PLT}}}
++ ${SDATA_GOT+${RELOCATING+${OTHER_GOT_SYMBOLS+. = .; ${OTHER_GOT_SYMBOLS}}}}
++ ${SDATA_GOT+${GOT}}
++ ${SDATA_GOT+${OTHER_GOT_SECTIONS}}
++ ${SDATA}
++ ${OTHER_SDATA_SECTIONS}
++ ${RELOCATING+${DATA_END_SYMBOLS-${USER_LABEL_PREFIX}_edata = .; PROVIDE (${USER_LABEL_PREFIX}edata = .);}}
++ ${RELOCATING+. = .;}
++ ${RELOCATING+${USER_LABEL_PREFIX}__bss_start = .;}
++ ${RELOCATING+${OTHER_BSS_SYMBOLS}}
++ ${SBSS}
++ ${BSS_PLT+${PLT}}
++ .${BSS_NAME} ${RELOCATING-0} :
++ {
++ PROVIDE (__bss_start = .);
++ *(.dyn${BSS_NAME})
++ *(.${BSS_NAME}${RELOCATING+ .${BSS_NAME}.* .gnu.linkonce.b.*})
++ *(COMMON)
++ /* Align here to ensure that the .bss section occupies space up to
++ _end. Align after .bss to ensure correct alignment even if the
++ .bss section disappears because there are no input sections.
++ FIXME: Why do we need it? When there is no .bss section, we don't
++ pad the .data section. */
++ ${RELOCATING+. = ALIGN(. != 0 ? ${ALIGNMENT} : 1);}
++ PROVIDE (__bss_end = .);
++ }
++ PROVIDE (__bss_size = SIZEOF(.bss));
++ ${OTHER_BSS_SECTIONS}
++ ${RELOCATING+${OTHER_BSS_END_SYMBOLS}}
++ ${RELOCATING+. = ALIGN(${ALIGNMENT});}
++ ${LARGE_SECTIONS}
++ ${RELOCATING+. = ALIGN(${ALIGNMENT});}
++ ${RELOCATING+${OTHER_END_SYMBOLS}}
++ ${RELOCATING+${END_SYMBOLS-${USER_LABEL_PREFIX}_end = .; PROVIDE (${USER_LABEL_PREFIX}end = .);}}
++ ${RELOCATING+${DATA_SEGMENT_END}}
++EOF
++
++test -z "${NON_ALLOC_DYN}" || emit_dyn
++
++cat <<EOF
++ /* Stabs debugging sections. */
++ .stab 0 : { *(.stab) }
++ .stabstr 0 : { *(.stabstr) }
++ .stab.excl 0 : { *(.stab.excl) }
++ .stab.exclstr 0 : { *(.stab.exclstr) }
++ .stab.index 0 : { *(.stab.index) }
++ .stab.indexstr 0 : { *(.stab.indexstr) }
++
++ .comment 0 : { *(.comment) }
++
++ /* DWARF debug sections.
++ Symbols in the DWARF debugging sections are relative to the beginning
++ of the section so we begin them at 0. */
++
++ /* DWARF 1 */
++ .debug 0 : { *(.debug) }
++ .line 0 : { *(.line) }
++
++ /* GNU DWARF 1 extensions */
++ .debug_srcinfo 0 : { *(.debug_srcinfo) }
++ .debug_sfnames 0 : { *(.debug_sfnames) }
++
++ /* DWARF 1.1 and DWARF 2 */
++ .debug_aranges 0 : { *(.debug_aranges) }
++ .debug_pubnames 0 : { *(.debug_pubnames) }
++
++ /* DWARF 2 */
++ .debug_info 0 : { *(.debug_info${RELOCATING+ .gnu.linkonce.wi.*}) }
++ .debug_abbrev 0 : { *(.debug_abbrev) }
++ .debug_line 0 : { *(.debug_line) }
++ .debug_frame 0 : { *(.debug_frame) }
++ .debug_str 0 : { *(.debug_str) }
++ .debug_loc 0 : { *(.debug_loc) }
++ .debug_macinfo 0 : { *(.debug_macinfo) }
++
++ /* SGI/MIPS DWARF 2 extensions */
++ .debug_weaknames 0 : { *(.debug_weaknames) }
++ .debug_funcnames 0 : { *(.debug_funcnames) }
++ .debug_typenames 0 : { *(.debug_typenames) }
++ .debug_varnames 0 : { *(.debug_varnames) }
++
++ /* DWARF 3 */
++ .debug_pubtypes 0 : { *(.debug_pubtypes) }
++ .debug_ranges 0 : { *(.debug_ranges) }
++
++ /* DWARF Extension. */
++ .debug_macro 0 : { *(.debug_macro) }
++
++ ${TINY_DATA_SECTION}
++ ${TINY_BSS_SECTION}
++
++ ${STACK_ADDR+${STACK}}
++ ${ATTRS_SECTIONS}
++ ${OTHER_SECTIONS}
++ ${RELOCATING+${OTHER_SYMBOLS}}
++ ${RELOCATING+${DISCARDED}}
++}
++EOF
+diff -ruN binutils-2.45/opcodes/ppc-dis.c binutils-2.45_mos/opcodes/ppc-dis.c
+--- binutils-2.45/opcodes/ppc-dis.c 2025-07-27 02:00:00.000000000 +0300
++++ binutils-2.45_mos/opcodes/ppc-dis.c 2025-07-27 14:39:08.712060584 +0300
+@@ -288,6 +288,8 @@
+ { "titan", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_PMR
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_TITAN),
+ 0 },
++ { "vec", PPC_OPCODE_PPC,
++ PPC_OPCODE_ALTIVEC },
+ { "vle", (PPC_OPCODE_PPC | PPC_OPCODE_BOOKE | PPC_OPCODE_SPE
+ | PPC_OPCODE_ISEL | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK | PPC_OPCODE_RFMCI
Home |
Main Index |
Thread Index |
Old Index