summaryrefslogtreecommitdiff
path: root/ld/emultempl/mmix-elfnmmo.em
diff options
context:
space:
mode:
Diffstat (limited to 'ld/emultempl/mmix-elfnmmo.em')
-rw-r--r--ld/emultempl/mmix-elfnmmo.em115
1 files changed, 115 insertions, 0 deletions
diff --git a/ld/emultempl/mmix-elfnmmo.em b/ld/emultempl/mmix-elfnmmo.em
new file mode 100644
index 0000000..5ef5e5e
--- /dev/null
+++ b/ld/emultempl/mmix-elfnmmo.em
@@ -0,0 +1,115 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright (C) 2001-2014 Free Software Foundation, Inc.
+#
+# 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.
+#
+
+# This file is sourced from elf32.em and mmo.em, used to define
+# MMIX-specific things common to ELF and MMO.
+
+fragment <<EOF
+#include "elf/mmix.h"
+
+/* Set up handling of linker-allocated global registers. */
+
+static void
+mmix_before_allocation (void)
+{
+ /* Call the default first. */
+ gld${EMULATION_NAME}_before_allocation ();
+
+ /* There's a needrelax.em which uses this ..._before_allocation-hook and
+ just has the statement below as payload. It's more of a hassle to
+ use that than to just include these two lines and take the
+ maintenance burden to keep them in sync. (Of course we lose the
+ maintenance burden of checking that it still does what we need.) */
+
+ /* Force -relax on (regardless of whether we're doing a relocatable
+ link). */
+ ENABLE_RELAXATION;
+
+ if (!_bfd_mmix_before_linker_allocation (link_info.output_bfd, &link_info))
+ einfo ("%X%P: Internal problems setting up section %s",
+ MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+}
+
+/* We need to set the VMA of the .MMIX.reg_contents section when it has
+ been allocated, and produce the final settings for the linker-generated
+ GREGs. */
+
+static void
+mmix_after_allocation (void)
+{
+ asection *sec;
+ bfd_signed_vma regvma;
+
+ gld${EMULATION_NAME}_after_allocation ();
+
+ /* If there's no register section, we don't need to do anything. On the
+ other hand, if there's a non-standard linker-script without a mapping
+ from MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME when that section is
+ present (as in the ld test "NOCROSSREFS 2"), that section (1) will be
+ orphaned; not inserted in MMIX_REG_CONTENTS_SECTION_NAME and (2) we
+ will not do the necessary preparations for those relocations that
+ caused it to be created. We'll SEGV from the latter error. The
+ former error in separation will result in a non-working binary, but
+ that's expected when you play tricks with linker scripts. The
+ "NOCROSSREFS 2" test does not run the output so it does not matter
+ there. */
+ sec = bfd_get_section_by_name (link_info.output_bfd,
+ MMIX_REG_CONTENTS_SECTION_NAME);
+ if (sec == NULL)
+ sec
+ = bfd_get_section_by_name (link_info.output_bfd,
+ MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
+ if (sec == NULL)
+ return;
+
+ regvma = 256 * 8 - sec->size - 8;
+
+ /* If we start on a local register, we have too many global registers.
+ We treat this error as nonfatal (meaning processing will continue in
+ search for other errors), because it's a link error in the same way
+ as an undefined symbol. */
+ if (regvma < 32 * 8)
+ {
+ einfo ("%X%P: Too many global registers: %u, max 223\n",
+ (unsigned) sec->size / 8);
+ regvma = 32 * 8;
+ }
+
+ /* Set vma to correspond to first such register number * 8. */
+ bfd_set_section_vma (link_info.output_bfd, sec, (bfd_vma) regvma);
+
+ /* Simplify symbol output for the register section (without contents;
+ created for register symbols) by setting the output offset to 0.
+ This section is only present when there are register symbols. */
+ sec = bfd_get_section_by_name (link_info.output_bfd, MMIX_REG_SECTION_NAME);
+ if (sec != NULL)
+ bfd_set_section_vma (sec->owner, sec, 0);
+
+ if (!_bfd_mmix_after_linker_allocation (link_info.output_bfd, &link_info))
+ {
+ /* This is a fatal error; make einfo call not return. */
+ einfo ("%F%P: Can't finalize linker-allocated global registers\n");
+ }
+}
+EOF
+
+LDEMUL_AFTER_ALLOCATION=mmix_after_allocation
+LDEMUL_BEFORE_ALLOCATION=mmix_before_allocation