xref: /openbsd/gnu/usr.bin/binutils/ld/emultempl/mmo.em (revision cf2f2c56)
1d2201f2fSdrahn# This shell script emits a C file. -*- C -*-
2*cf2f2c56Smiod#   Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
3d2201f2fSdrahn#
4d2201f2fSdrahn# This file is part of GLD, the Gnu Linker.
5d2201f2fSdrahn#
6d2201f2fSdrahn# This program is free software; you can redistribute it and/or modify
7d2201f2fSdrahn# it under the terms of the GNU General Public License as published by
8d2201f2fSdrahn# the Free Software Foundation; either version 2 of the License, or
9d2201f2fSdrahn# (at your option) any later version.
10d2201f2fSdrahn#
11d2201f2fSdrahn# This program is distributed in the hope that it will be useful,
12d2201f2fSdrahn# but WITHOUT ANY WARRANTY; without even the implied warranty of
13d2201f2fSdrahn# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14d2201f2fSdrahn# GNU General Public License for more details.
15d2201f2fSdrahn#
16d2201f2fSdrahn# You should have received a copy of the GNU General Public License
17d2201f2fSdrahn# along with this program; if not, write to the Free Software
18d2201f2fSdrahn# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19d2201f2fSdrahn#
20d2201f2fSdrahn
21d2201f2fSdrahn# This file is sourced from elf32.em and mmo.em, used to define
22d2201f2fSdrahn# linker MMIX-specifics common to ELF and MMO.
23d2201f2fSdrahn
24d2201f2fSdrahncat >>e${EMULATION_NAME}.c <<EOF
25d2201f2fSdrahn/* Need to have this define before mmix-elfnmmo, which includes
26d2201f2fSdrahn   needrelax.em which uses this name for the before_allocation function,
27d2201f2fSdrahn   normally defined in elf32.em.  */
28d2201f2fSdrahn#define gldmmo_before_allocation before_allocation_default
29d2201f2fSdrahnEOF
30d2201f2fSdrahn
31d2201f2fSdrahn. ${srcdir}/emultempl/mmix-elfnmmo.em
32d2201f2fSdrahn
33d2201f2fSdrahncat >>e${EMULATION_NAME}.c <<EOF
34d2201f2fSdrahn
35d2201f2fSdrahn/* Find the last output section before given output statement.
36d2201f2fSdrahn   Used by place_orphan.  */
37d2201f2fSdrahn
38d2201f2fSdrahnstatic asection *
39*cf2f2c56Smiodoutput_prev_sec_find (lang_output_section_statement_type *os)
40d2201f2fSdrahn{
41*cf2f2c56Smiod  asection *s = NULL;
42d2201f2fSdrahn  lang_statement_union_type *u;
43d2201f2fSdrahn  lang_output_section_statement_type *lookup;
44d2201f2fSdrahn
45d2201f2fSdrahn  for (u = lang_output_section_statement.head;
46d2201f2fSdrahn       u != (lang_statement_union_type *) NULL;
47d2201f2fSdrahn       u = lookup->next)
48d2201f2fSdrahn    {
49d2201f2fSdrahn      lookup = &u->output_section_statement;
50d2201f2fSdrahn      if (lookup == os)
51d2201f2fSdrahn	break;
52d2201f2fSdrahn      if (lookup->bfd_section != NULL
53d2201f2fSdrahn	  && lookup->bfd_section != bfd_abs_section_ptr
54d2201f2fSdrahn	  && lookup->bfd_section != bfd_com_section_ptr
55d2201f2fSdrahn	  && lookup->bfd_section != bfd_und_section_ptr)
56d2201f2fSdrahn	s = lookup->bfd_section;
57d2201f2fSdrahn    }
58d2201f2fSdrahn
59d2201f2fSdrahn  if (u == NULL)
60d2201f2fSdrahn    return NULL;
61d2201f2fSdrahn
62d2201f2fSdrahn  return s;
63d2201f2fSdrahn}
64d2201f2fSdrahn
65d2201f2fSdrahnstruct orphan_save {
66d2201f2fSdrahn  lang_output_section_statement_type *os;
67d2201f2fSdrahn  asection **section;
68d2201f2fSdrahn  lang_statement_union_type **stmt;
69d2201f2fSdrahn};
70d2201f2fSdrahn
71d2201f2fSdrahn#define HAVE_SECTION(hold, name) \
72d2201f2fSdrahn(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
73d2201f2fSdrahn
74d2201f2fSdrahn/* Place an orphan section.  We use this to put random SEC_CODE or
75d2201f2fSdrahn   SEC_READONLY sections right after MMO_TEXT_SECTION_NAME.  Much borrowed
76d2201f2fSdrahn   from elf32.em.  */
77d2201f2fSdrahn
78d2201f2fSdrahnstatic bfd_boolean
79*cf2f2c56Smiodmmo_place_orphan (lang_input_statement_type *file, asection *s)
80d2201f2fSdrahn{
81d2201f2fSdrahn  static struct orphan_save hold_text;
82d2201f2fSdrahn  struct orphan_save *place;
83d2201f2fSdrahn  lang_output_section_statement_type *os;
84d2201f2fSdrahn  lang_statement_list_type *old;
85d2201f2fSdrahn  lang_statement_list_type add;
86d2201f2fSdrahn  asection *snew, **pps, *bfd_section;
87d2201f2fSdrahn
88d2201f2fSdrahn  /* We have nothing to say for anything other than a final link.  */
89*cf2f2c56Smiod  if (link_info.relocatable
90d2201f2fSdrahn      || (bfd_get_section_flags (s->owner, s)
91d2201f2fSdrahn	  & (SEC_EXCLUDE | SEC_LOAD)) != SEC_LOAD)
92d2201f2fSdrahn    return FALSE;
93d2201f2fSdrahn
94d2201f2fSdrahn  /* Only care for sections we're going to load.  */
95d2201f2fSdrahn  os = lang_output_section_find (bfd_get_section_name (s->owner, s));
96d2201f2fSdrahn
97d2201f2fSdrahn  /* We have an output section by this name.  Place the section inside it
98d2201f2fSdrahn     (regardless of whether the linker script lists it as input).  */
99d2201f2fSdrahn  if (os != NULL)
100d2201f2fSdrahn    {
101d2201f2fSdrahn      lang_add_section (&os->children, s, os, file);
102d2201f2fSdrahn      return TRUE;
103d2201f2fSdrahn    }
104d2201f2fSdrahn
105d2201f2fSdrahn  /* If this section does not have .text-type section flags or there's no
106d2201f2fSdrahn     MMO_TEXT_SECTION_NAME, we don't have anything to say.  */
107d2201f2fSdrahn  if ((bfd_get_section_flags (s->owner, s) & (SEC_CODE | SEC_READONLY)) == 0)
108d2201f2fSdrahn    return FALSE;
109d2201f2fSdrahn
110d2201f2fSdrahn  if (hold_text.os == NULL)
111d2201f2fSdrahn    hold_text.os = lang_output_section_find (MMO_TEXT_SECTION_NAME);
112d2201f2fSdrahn
113d2201f2fSdrahn  place = &hold_text;
114d2201f2fSdrahn
115d2201f2fSdrahn  /* If there's an output section by this name, we'll use it, regardless
116d2201f2fSdrahn     of section flags, in contrast to what's done in elf32.em.  */
117d2201f2fSdrahn
118d2201f2fSdrahn  /* Start building a list of statements for this section.
119d2201f2fSdrahn     First save the current statement pointer.  */
120d2201f2fSdrahn  old = stat_ptr;
121d2201f2fSdrahn
122d2201f2fSdrahn  /* Add the output section statements for this orphan to our own private
123d2201f2fSdrahn     list, inserting them later into the global statement list.  */
124d2201f2fSdrahn  stat_ptr = &add;
125d2201f2fSdrahn  lang_list_init (stat_ptr);
126d2201f2fSdrahn
127d2201f2fSdrahn  os = lang_enter_output_section_statement (bfd_get_section_name (s->owner,
128d2201f2fSdrahn								  s),
129d2201f2fSdrahn					    NULL, 0,
130d2201f2fSdrahn					    (etree_type *) NULL,
131d2201f2fSdrahn					    (etree_type *) NULL,
132d2201f2fSdrahn					    (etree_type *) NULL);
133d2201f2fSdrahn
134d2201f2fSdrahn  lang_add_section (&os->children, s, os, file);
135d2201f2fSdrahn
136d2201f2fSdrahn  lang_leave_output_section_statement
137d2201f2fSdrahn    ((bfd_vma) 0, "*default*",
138d2201f2fSdrahn     (struct lang_output_section_phdr_list *) NULL, NULL);
139d2201f2fSdrahn
140d2201f2fSdrahn  /* Restore the global list pointer.  */
141d2201f2fSdrahn  stat_ptr = old;
142d2201f2fSdrahn
143d2201f2fSdrahn  snew = os->bfd_section;
144d2201f2fSdrahn  if (snew == NULL)
145d2201f2fSdrahn    /* /DISCARD/ section.  */
146d2201f2fSdrahn    return TRUE;
147d2201f2fSdrahn
148d2201f2fSdrahn  /* We need an output section for .text as a root, so if there was none
149d2201f2fSdrahn     (might happen with a peculiar linker script such as in "map
150d2201f2fSdrahn     addresses", map-address.exp), we grab the output section created
151d2201f2fSdrahn     above.  */
152d2201f2fSdrahn  if (hold_text.os == NULL)
153d2201f2fSdrahn    {
154d2201f2fSdrahn      if (os == NULL)
155d2201f2fSdrahn	return FALSE;
156d2201f2fSdrahn      hold_text.os = os;
157d2201f2fSdrahn    }
158d2201f2fSdrahn
159d2201f2fSdrahn  bfd_section = place->os->bfd_section;
160d2201f2fSdrahn  if (place->section == NULL && bfd_section == NULL)
161d2201f2fSdrahn    bfd_section = output_prev_sec_find (place->os);
162d2201f2fSdrahn
163d2201f2fSdrahn  if (place->section != NULL
164d2201f2fSdrahn      || (bfd_section != NULL
165d2201f2fSdrahn	  && bfd_section != snew))
166d2201f2fSdrahn    {
167d2201f2fSdrahn      /* Shuffle the section to make the output file look neater.  This is
168d2201f2fSdrahn	 really only cosmetic.  */
169d2201f2fSdrahn      if (place->section == NULL)
170d2201f2fSdrahn	/* Put orphans after the first section on the list.  */
171d2201f2fSdrahn	place->section = &bfd_section->next;
172d2201f2fSdrahn
173d2201f2fSdrahn      /* Unlink the section.  */
174d2201f2fSdrahn      for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
175d2201f2fSdrahn	;
176d2201f2fSdrahn      bfd_section_list_remove (output_bfd, pps);
177d2201f2fSdrahn
178d2201f2fSdrahn      /* Now tack it on to the "place->os" section list.  */
179d2201f2fSdrahn      bfd_section_list_insert (output_bfd, place->section, snew);
180d2201f2fSdrahn    }
181d2201f2fSdrahn  place->section = &snew->next;	/* Save the end of this list.  */
182d2201f2fSdrahn
183d2201f2fSdrahn  if (add.head != NULL)
184d2201f2fSdrahn    {
185d2201f2fSdrahn      /* We try to put the output statements in some sort of reasonable
186d2201f2fSdrahn	 order here, because they determine the final load addresses of
187d2201f2fSdrahn	 the orphan sections.  */
188d2201f2fSdrahn      if (place->stmt == NULL)
189d2201f2fSdrahn	{
190d2201f2fSdrahn	  /* Put the new statement list right at the head.  */
191d2201f2fSdrahn	  *add.tail = place->os->header.next;
192d2201f2fSdrahn	  place->os->header.next = add.head;
193d2201f2fSdrahn	}
194d2201f2fSdrahn      else
195d2201f2fSdrahn	{
196d2201f2fSdrahn	  /* Put it after the last orphan statement we added.  */
197d2201f2fSdrahn	  *add.tail = *place->stmt;
198d2201f2fSdrahn	  *place->stmt = add.head;
199d2201f2fSdrahn	}
200d2201f2fSdrahn
201d2201f2fSdrahn      /* Fix the global list pointer if we happened to tack our new list
202d2201f2fSdrahn	 at the tail.  */
203d2201f2fSdrahn      if (*old->tail == add.head)
204d2201f2fSdrahn	old->tail = add.tail;
205d2201f2fSdrahn
206d2201f2fSdrahn      /* Save the end of this list.  */
207d2201f2fSdrahn      place->stmt = add.tail;
208d2201f2fSdrahn    }
209d2201f2fSdrahn
210d2201f2fSdrahn  return TRUE;
211d2201f2fSdrahn}
212d2201f2fSdrahn
213d2201f2fSdrahn/* Remove the spurious settings of SEC_RELOC that make it to the output at
214d2201f2fSdrahn   link time.  We are as confused as elflink.h:elf_bfd_final_link, and
215d2201f2fSdrahn   paper over the bug similarly.  */
216d2201f2fSdrahn
217d2201f2fSdrahnstatic void
218*cf2f2c56Smiodmmo_wipe_sec_reloc_flag (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
219d2201f2fSdrahn{
220d2201f2fSdrahn  bfd_set_section_flags (abfd, sec,
221d2201f2fSdrahn			 bfd_get_section_flags (abfd, sec) & ~SEC_RELOC);
222d2201f2fSdrahn}
223d2201f2fSdrahn
224d2201f2fSdrahn/* Iterate with bfd_map_over_sections over mmo_wipe_sec_reloc_flag... */
225d2201f2fSdrahn
226d2201f2fSdrahnstatic void
227*cf2f2c56Smiodmmo_finish (void)
228d2201f2fSdrahn{
229d2201f2fSdrahn  bfd_map_over_sections (output_bfd, mmo_wipe_sec_reloc_flag, NULL);
230d2201f2fSdrahn}
231d2201f2fSdrahn
232d2201f2fSdrahn/* To get on-demand global register allocation right, we need to parse the
233d2201f2fSdrahn   relocs, like what happens when linking to ELF.  It needs to be done
234d2201f2fSdrahn   before all input sections are supposed to be present.  When linking to
235d2201f2fSdrahn   ELF, it's done when reading symbols.  When linking to mmo, we do it
236d2201f2fSdrahn   when all input files are seen, which is equivalent.  */
237d2201f2fSdrahn
238d2201f2fSdrahnstatic void
239*cf2f2c56Smiodmmo_after_open (void)
240d2201f2fSdrahn{
241d2201f2fSdrahn  /* When there's a mismatch between the output format and the emulation
242d2201f2fSdrahn     (using weird combinations like "-m mmo --oformat elf64-mmix" for
243d2201f2fSdrahn     example), we'd count relocs twice because they'd also be counted
244d2201f2fSdrahn     along the usual route for ELF-only linking, which would lead to an
245d2201f2fSdrahn     internal accounting error.  */
246d2201f2fSdrahn  if (bfd_get_flavour (output_bfd) != bfd_target_elf_flavour)
247d2201f2fSdrahn    {
248d2201f2fSdrahn      LANG_FOR_EACH_INPUT_STATEMENT (is)
249d2201f2fSdrahn	{
250d2201f2fSdrahn	  if (bfd_get_flavour (is->the_bfd) == bfd_target_elf_flavour
251d2201f2fSdrahn	      && !_bfd_mmix_check_all_relocs (is->the_bfd, &link_info))
252d2201f2fSdrahn	    einfo ("%X%P: Internal problems scanning %B after opening it",
253d2201f2fSdrahn		   is->the_bfd);
254d2201f2fSdrahn	}
255d2201f2fSdrahn    }
256d2201f2fSdrahn}
257d2201f2fSdrahnEOF
258d2201f2fSdrahn
259d2201f2fSdrahnLDEMUL_PLACE_ORPHAN=mmo_place_orphan
260d2201f2fSdrahnLDEMUL_FINISH=mmo_finish
261d2201f2fSdrahnLDEMUL_AFTER_OPEN=mmo_after_open
262