aboutsummaryrefslogtreecommitdiff
path: root/ld/emultempl/mmix-elfnmmo.em
blob: 44223a89bbd751a124295f14720b679135a3e397 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# This shell script emits a C file. -*- C -*-
#   Copyright 2001, 2002 Free Software Foundation, Inc.
#
# This file is part of GLD, the Gnu Linker.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#

# This file is sourced from elf32.em and mmo.em, used to define
# MMIX-specific things common to ELF and MMO.

cat >>e${EMULATION_NAME}.c <<EOF
#include "elf/mmix.h"

static void mmix_before_allocation PARAMS ((void));
static void mmix_after_allocation PARAMS ((void));

/* Set up handling of linker-allocated global registers.  */

static void
mmix_before_allocation ()
{
  /* 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 if not doing a relocatable link.  */
  if (! link_info.relocateable)
    command_line.relax = true;

  if (!_bfd_mmix_prepare_linker_allocated_gregs (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 ()
{
  asection *sec
    = bfd_get_section_by_name (output_bfd, MMIX_REG_CONTENTS_SECTION_NAME);
  bfd_signed_vma regvma;

  /* If there's no register section, we don't need to do anything.  On the
     other hand, if a non-standard linker-script without a mapping from
     MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME 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.  */
  if (sec == NULL)
    sec
      = bfd_get_section_by_name (output_bfd,
				 MMIX_LD_ALLOCATED_REG_CONTENTS_SECTION_NAME);
  if (sec == NULL)
    return;

  regvma = 256 * 8 - sec->_raw_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->_raw_size / 8);
      regvma = 32 * 8;
    }

  /* Set vma to correspond to first such register number * 8.  */
  bfd_set_section_vma (output_bfd, sec, (bfd_vma) regvma);

  /* ??? Why isn't the section size (_cooked_size) set?  Doesn't it get
     set regardless of presence of relocations?  */
  if (sec->_cooked_size == 0
      && ! bfd_set_section_size (output_bfd, sec, sec->_raw_size))
    {
      /* This is a fatal error; make the einfo call not return.  */
      einfo ("%F%P: Can't set section %s size to %u\n",
	     MMIX_REG_CONTENTS_SECTION_NAME, (unsigned) sec->_raw_size);
    }

  /* 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 (output_bfd, MMIX_REG_SECTION_NAME);
  if (sec != NULL)
    bfd_set_section_vma (abfd, sec, 0);

  if (!_bfd_mmix_finalize_linker_allocated_gregs (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