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