12159047fSniklas# This shell script emits a C file. -*- C -*- 2c074d1c9Sdrahn# Copyright 1991, 1993, 1994, 1997, 1999, 2000, 2001, 2002, 2003 3b55d4692Sfgsch# Free Software Foundation, Inc. 4b55d4692Sfgsch# 5b55d4692Sfgsch# This file is part of GLD, the Gnu Linker. 6b55d4692Sfgsch# 7b55d4692Sfgsch# This program is free software; you can redistribute it and/or modify 8b55d4692Sfgsch# it under the terms of the GNU General Public License as published by 9b55d4692Sfgsch# the Free Software Foundation; either version 2 of the License, or 10b55d4692Sfgsch# (at your option) any later version. 11b55d4692Sfgsch# 12b55d4692Sfgsch# This program is distributed in the hope that it will be useful, 13b55d4692Sfgsch# but WITHOUT ANY WARRANTY; without even the implied warranty of 14b55d4692Sfgsch# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15b55d4692Sfgsch# GNU General Public License for more details. 16b55d4692Sfgsch# 17b55d4692Sfgsch# You should have received a copy of the GNU General Public License 18b55d4692Sfgsch# along with this program; if not, write to the Free Software 19b55d4692Sfgsch# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20b55d4692Sfgsch# 212159047fSniklas 22b55d4692Sfgsch# This file is sourced from elf32.em, and defines extra hppa-elf 23b55d4692Sfgsch# specific routines. 24b55d4692Sfgsch# 25b55d4692Sfgschcat >>e${EMULATION_NAME}.c <<EOF 262159047fSniklas 272159047fSniklas#include "ldctor.h" 28b55d4692Sfgsch#include "elf32-hppa.h" 292159047fSniklas 30b55d4692Sfgsch 31b55d4692Sfgsch/* Fake input file for stubs. */ 322159047fSniklasstatic lang_input_statement_type *stub_file; 332159047fSniklas 34b55d4692Sfgsch/* Type of import/export stubs to build. For a single sub-space model, 35b55d4692Sfgsch we can build smaller import stubs and there is no need for export 36b55d4692Sfgsch stubs. */ 37b55d4692Sfgschstatic int multi_subspace = 0; 382159047fSniklas 39c074d1c9Sdrahn/* Whether we need to call hppa_layout_sections_again. */ 40c074d1c9Sdrahnstatic int need_laying_out = 0; 41c074d1c9Sdrahn 42b55d4692Sfgsch/* Maximum size of a group of input sections that can be handled by 43b55d4692Sfgsch one stub section. A value of +/-1 indicates the bfd back-end 44b55d4692Sfgsch should use a suitable default size. */ 45b55d4692Sfgschstatic bfd_signed_vma group_size = 1; 462159047fSniklas 47b55d4692Sfgsch/* Stops the linker merging .text sections on a relocatable link, 48b55d4692Sfgsch and adds millicode library to the list of input files. */ 492159047fSniklas 502159047fSniklasstatic void 51*007c2a45Smiodhppaelf_after_parse (void) 522159047fSniklas{ 53*007c2a45Smiod if (link_info.relocatable) 54b55d4692Sfgsch lang_add_unique (".text"); 55c074d1c9Sdrahn#if 0 /* Enable this once we split millicode stuff from libgcc. */ 56b55d4692Sfgsch else 57b55d4692Sfgsch lang_add_input_file ("milli", 58b55d4692Sfgsch lang_input_file_is_l_enum, 59b55d4692Sfgsch NULL); 60b55d4692Sfgsch#endif 612159047fSniklas} 622159047fSniklas 632159047fSniklas/* This is called before the input files are opened. We create a new 64b55d4692Sfgsch fake input file to hold the stub sections. */ 652159047fSniklas 662159047fSniklasstatic void 67*007c2a45Smiodhppaelf_create_output_section_statements (void) 682159047fSniklas{ 69*007c2a45Smiod extern const bfd_target bfd_elf32_hppa_linux_vec; 70*007c2a45Smiod extern const bfd_target bfd_elf32_hppa_vec; 71*007c2a45Smiod 72*007c2a45Smiod if (link_info.hash->creator != &bfd_elf32_hppa_linux_vec 73*007c2a45Smiod && link_info.hash->creator != &bfd_elf32_hppa_vec) 74*007c2a45Smiod return; 75*007c2a45Smiod 762159047fSniklas stub_file = lang_add_input_file ("linker stubs", 772159047fSniklas lang_input_file_is_fake_enum, 782159047fSniklas NULL); 792159047fSniklas stub_file->the_bfd = bfd_create ("linker stubs", output_bfd); 802159047fSniklas if (stub_file->the_bfd == NULL 812159047fSniklas || ! bfd_set_arch_mach (stub_file->the_bfd, 822159047fSniklas bfd_get_arch (output_bfd), 832159047fSniklas bfd_get_mach (output_bfd))) 842159047fSniklas { 852159047fSniklas einfo ("%X%P: can not create BFD %E\n"); 862159047fSniklas return; 872159047fSniklas } 882159047fSniklas 892159047fSniklas ldlang_add_file (stub_file); 902159047fSniklas} 912159047fSniklas 92b55d4692Sfgsch 93b55d4692Sfgschstruct hook_stub_info 94b55d4692Sfgsch{ 95b55d4692Sfgsch lang_statement_list_type add; 96b55d4692Sfgsch asection *input_section; 97b55d4692Sfgsch}; 98b55d4692Sfgsch 99b55d4692Sfgsch/* Traverse the linker tree to find the spot where the stub goes. */ 100b55d4692Sfgsch 101c074d1c9Sdrahnstatic bfd_boolean 102*007c2a45Smiodhook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp) 103b55d4692Sfgsch{ 104b55d4692Sfgsch lang_statement_union_type *l; 105c074d1c9Sdrahn bfd_boolean ret; 106b55d4692Sfgsch 107c074d1c9Sdrahn for (; (l = *lp) != NULL; lp = &l->header.next) 108b55d4692Sfgsch { 109b55d4692Sfgsch switch (l->header.type) 110b55d4692Sfgsch { 111b55d4692Sfgsch case lang_constructors_statement_enum: 112b55d4692Sfgsch ret = hook_in_stub (info, &constructor_list.head); 113b55d4692Sfgsch if (ret) 114b55d4692Sfgsch return ret; 115b55d4692Sfgsch break; 116b55d4692Sfgsch 117b55d4692Sfgsch case lang_output_section_statement_enum: 118b55d4692Sfgsch ret = hook_in_stub (info, 119b55d4692Sfgsch &l->output_section_statement.children.head); 120b55d4692Sfgsch if (ret) 121b55d4692Sfgsch return ret; 122b55d4692Sfgsch break; 123b55d4692Sfgsch 124b55d4692Sfgsch case lang_wild_statement_enum: 125b55d4692Sfgsch ret = hook_in_stub (info, &l->wild_statement.children.head); 126b55d4692Sfgsch if (ret) 127b55d4692Sfgsch return ret; 128b55d4692Sfgsch break; 129b55d4692Sfgsch 130b55d4692Sfgsch case lang_group_statement_enum: 131b55d4692Sfgsch ret = hook_in_stub (info, &l->group_statement.children.head); 132b55d4692Sfgsch if (ret) 133b55d4692Sfgsch return ret; 134b55d4692Sfgsch break; 135b55d4692Sfgsch 136b55d4692Sfgsch case lang_input_section_enum: 137b55d4692Sfgsch if (l->input_section.section == info->input_section) 138b55d4692Sfgsch { 139b55d4692Sfgsch /* We've found our section. Insert the stub immediately 140b55d4692Sfgsch before its associated input section. */ 141b55d4692Sfgsch *lp = info->add.head; 142b55d4692Sfgsch *(info->add.tail) = l; 143c074d1c9Sdrahn return TRUE; 144b55d4692Sfgsch } 145b55d4692Sfgsch break; 146b55d4692Sfgsch 147b55d4692Sfgsch case lang_data_statement_enum: 148b55d4692Sfgsch case lang_reloc_statement_enum: 149b55d4692Sfgsch case lang_object_symbols_statement_enum: 150b55d4692Sfgsch case lang_output_statement_enum: 151b55d4692Sfgsch case lang_target_statement_enum: 152b55d4692Sfgsch case lang_input_statement_enum: 153b55d4692Sfgsch case lang_assignment_statement_enum: 154b55d4692Sfgsch case lang_padding_statement_enum: 155b55d4692Sfgsch case lang_address_statement_enum: 156b55d4692Sfgsch case lang_fill_statement_enum: 157b55d4692Sfgsch break; 158b55d4692Sfgsch 159b55d4692Sfgsch default: 160b55d4692Sfgsch FAIL (); 161b55d4692Sfgsch break; 162b55d4692Sfgsch } 163b55d4692Sfgsch } 164c074d1c9Sdrahn return FALSE; 165b55d4692Sfgsch} 166b55d4692Sfgsch 167b55d4692Sfgsch 168b55d4692Sfgsch/* Call-back for elf32_hppa_size_stubs. */ 169b55d4692Sfgsch 170b55d4692Sfgsch/* Create a new stub section, and arrange for it to be linked 171b55d4692Sfgsch immediately before INPUT_SECTION. */ 172b55d4692Sfgsch 173b55d4692Sfgschstatic asection * 174*007c2a45Smiodhppaelf_add_stub_section (const char *stub_sec_name, asection *input_section) 175b55d4692Sfgsch{ 176b55d4692Sfgsch asection *stub_sec; 177b55d4692Sfgsch flagword flags; 178b55d4692Sfgsch asection *output_section; 179b55d4692Sfgsch const char *secname; 180b55d4692Sfgsch lang_output_section_statement_type *os; 181b55d4692Sfgsch struct hook_stub_info info; 182b55d4692Sfgsch 183b55d4692Sfgsch stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_sec_name); 184b55d4692Sfgsch if (stub_sec == NULL) 185b55d4692Sfgsch goto err_ret; 186b55d4692Sfgsch 187b55d4692Sfgsch flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE 188b55d4692Sfgsch | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); 189b55d4692Sfgsch if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags)) 190b55d4692Sfgsch goto err_ret; 191b55d4692Sfgsch 192b55d4692Sfgsch output_section = input_section->output_section; 193b55d4692Sfgsch secname = bfd_get_section_name (output_section->owner, output_section); 194b55d4692Sfgsch os = lang_output_section_find (secname); 195b55d4692Sfgsch 196b55d4692Sfgsch info.input_section = input_section; 197b55d4692Sfgsch lang_list_init (&info.add); 198c074d1c9Sdrahn lang_add_section (&info.add, stub_sec, os, stub_file); 199b55d4692Sfgsch 200b55d4692Sfgsch if (info.add.head == NULL) 201b55d4692Sfgsch goto err_ret; 202b55d4692Sfgsch 203b55d4692Sfgsch if (hook_in_stub (&info, &os->children.head)) 204b55d4692Sfgsch return stub_sec; 205b55d4692Sfgsch 206b55d4692Sfgsch err_ret: 207b55d4692Sfgsch einfo ("%X%P: can not make stub section: %E\n"); 208b55d4692Sfgsch return NULL; 209b55d4692Sfgsch} 210b55d4692Sfgsch 211b55d4692Sfgsch 212b55d4692Sfgsch/* Another call-back for elf32_hppa_size_stubs. */ 2132159047fSniklas 2142159047fSniklasstatic void 215*007c2a45Smiodhppaelf_layout_sections_again (void) 2162159047fSniklas{ 217b55d4692Sfgsch /* If we have changed sizes of the stub sections, then we need 218b55d4692Sfgsch to recalculate all the section offsets. This may mean we need to 219b55d4692Sfgsch add even more stubs. */ 220c074d1c9Sdrahn need_laying_out = 0; 2212159047fSniklas 222c074d1c9Sdrahn lang_reset_memory_regions (); 2232159047fSniklas 2242159047fSniklas /* Resize the sections. */ 2252159047fSniklas lang_size_sections (stat_ptr->head, abs_output_section, 226c074d1c9Sdrahn &stat_ptr->head, 0, (bfd_vma) 0, NULL, TRUE); 2272159047fSniklas 2282159047fSniklas /* Redo special stuff. */ 2292159047fSniklas ldemul_after_allocation (); 2302159047fSniklas 2312159047fSniklas /* Do the assignments again. */ 232b55d4692Sfgsch lang_do_assignments (stat_ptr->head, abs_output_section, 233c074d1c9Sdrahn (fill_type *) 0, (bfd_vma) 0); 234c074d1c9Sdrahn} 235c074d1c9Sdrahn 236c074d1c9Sdrahn 237c074d1c9Sdrahnstatic void 238*007c2a45Smiodbuild_section_lists (lang_statement_union_type *statement) 239c074d1c9Sdrahn{ 240c074d1c9Sdrahn if (statement->header.type == lang_input_section_enum 241c074d1c9Sdrahn && !statement->input_section.ifile->just_syms_flag 242c074d1c9Sdrahn && statement->input_section.section->output_section != NULL 243c074d1c9Sdrahn && statement->input_section.section->output_section->owner == output_bfd) 244c074d1c9Sdrahn { 245c074d1c9Sdrahn elf32_hppa_next_input_section (&link_info, 246c074d1c9Sdrahn statement->input_section.section); 247c074d1c9Sdrahn } 248b55d4692Sfgsch} 2492159047fSniklas 250b55d4692Sfgsch 251b55d4692Sfgsch/* Final emulation specific call. For the PA we use this opportunity 252b55d4692Sfgsch to build linker stubs. */ 253b55d4692Sfgsch 254b55d4692Sfgschstatic void 255*007c2a45Smiodgld${EMULATION_NAME}_finish (void) 2562159047fSniklas{ 257*007c2a45Smiod /* bfd_elf_discard_info just plays with debugging sections, 258c074d1c9Sdrahn ie. doesn't affect any code, so we can delay resizing the 259c074d1c9Sdrahn sections. It's likely we'll resize everything in the process of 260c074d1c9Sdrahn adding stubs. */ 261*007c2a45Smiod if (bfd_elf_discard_info (output_bfd, &link_info)) 262c074d1c9Sdrahn need_laying_out = 1; 263c074d1c9Sdrahn 264b55d4692Sfgsch /* If generating a relocatable output file, then we don't 265b55d4692Sfgsch have to examine the relocs. */ 266*007c2a45Smiod if (stub_file != NULL && !link_info.relocatable) 267c074d1c9Sdrahn { 268c074d1c9Sdrahn int ret = elf32_hppa_setup_section_lists (output_bfd, &link_info); 269c074d1c9Sdrahn 270c074d1c9Sdrahn if (ret != 0) 271c074d1c9Sdrahn { 272c074d1c9Sdrahn if (ret < 0) 273c074d1c9Sdrahn { 274c074d1c9Sdrahn einfo ("%X%P: can not size stub section: %E\n"); 275b55d4692Sfgsch return; 276c074d1c9Sdrahn } 277c074d1c9Sdrahn 278c074d1c9Sdrahn lang_for_each_statement (build_section_lists); 279b55d4692Sfgsch 280b55d4692Sfgsch /* Call into the BFD backend to do the real work. */ 281b55d4692Sfgsch if (! elf32_hppa_size_stubs (output_bfd, 282b55d4692Sfgsch stub_file->the_bfd, 283b55d4692Sfgsch &link_info, 284b55d4692Sfgsch multi_subspace, 285b55d4692Sfgsch group_size, 286b55d4692Sfgsch &hppaelf_add_stub_section, 287c074d1c9Sdrahn &hppaelf_layout_sections_again)) 288b55d4692Sfgsch { 289b55d4692Sfgsch einfo ("%X%P: can not size stub section: %E\n"); 2902159047fSniklas return; 2912159047fSniklas } 292c074d1c9Sdrahn } 293c074d1c9Sdrahn } 294b55d4692Sfgsch 295c074d1c9Sdrahn if (need_laying_out) 296c074d1c9Sdrahn hppaelf_layout_sections_again (); 297c074d1c9Sdrahn 298*007c2a45Smiod if (! link_info.relocatable) 299c074d1c9Sdrahn { 300b55d4692Sfgsch /* Set the global data pointer. */ 301b55d4692Sfgsch if (! elf32_hppa_set_gp (output_bfd, &link_info)) 302b55d4692Sfgsch { 303b55d4692Sfgsch einfo ("%X%P: can not set gp\n"); 304b55d4692Sfgsch return; 305b55d4692Sfgsch } 306b55d4692Sfgsch 307b55d4692Sfgsch /* Now build the linker stubs. */ 308*007c2a45Smiod if (stub_file != NULL && stub_file->the_bfd->sections != NULL) 309b55d4692Sfgsch { 310b55d4692Sfgsch if (! elf32_hppa_build_stubs (&link_info)) 311b55d4692Sfgsch einfo ("%X%P: can not build stubs: %E\n"); 3122159047fSniklas } 3132159047fSniklas } 314c074d1c9Sdrahn} 3152159047fSniklas 3162159047fSniklas 317b55d4692Sfgsch/* Avoid processing the fake stub_file in vercheck, stat_needed and 318b55d4692Sfgsch check_needed routines. */ 3192159047fSniklas 320*007c2a45Smiodstatic void (*real_func) (lang_input_statement_type *); 3212159047fSniklas 322*007c2a45Smiodstatic void hppa_for_each_input_file_wrapper (lang_input_statement_type *l) 3232159047fSniklas{ 324b55d4692Sfgsch if (l != stub_file) 325b55d4692Sfgsch (*real_func) (l); 3262159047fSniklas} 3272159047fSniklas 328b55d4692Sfgschstatic void 329*007c2a45Smiodhppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) 3302159047fSniklas{ 331b55d4692Sfgsch real_func = func; 332b55d4692Sfgsch lang_for_each_input_file (&hppa_for_each_input_file_wrapper); 333b55d4692Sfgsch} 334b55d4692Sfgsch 335b55d4692Sfgsch#define lang_for_each_input_file hppa_lang_for_each_input_file 336b55d4692Sfgsch 3372159047fSniklasEOF 338b55d4692Sfgsch 339b55d4692Sfgsch# Define some shell vars to insert bits of code into the standard elf 340b55d4692Sfgsch# parse_args and list_options functions. 341b55d4692Sfgsch# 342b55d4692SfgschPARSE_AND_LIST_PROLOGUE=' 343b55d4692Sfgsch#define OPTION_MULTI_SUBSPACE 301 344b55d4692Sfgsch#define OPTION_STUBGROUP_SIZE (OPTION_MULTI_SUBSPACE + 1) 345b55d4692Sfgsch' 346b55d4692Sfgsch 347b55d4692SfgschPARSE_AND_LIST_LONGOPTS=' 348b55d4692Sfgsch { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE }, 349b55d4692Sfgsch { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, 350b55d4692Sfgsch' 351b55d4692Sfgsch 352b55d4692SfgschPARSE_AND_LIST_OPTIONS=' 353b55d4692Sfgsch fprintf (file, _("\ 354b55d4692Sfgsch --multi-subspace Generate import and export stubs to support\n\ 355b55d4692Sfgsch multiple sub-space shared libraries\n" 356b55d4692Sfgsch )); 357b55d4692Sfgsch fprintf (file, _("\ 358b55d4692Sfgsch --stub-group-size=N Maximum size of a group of input sections that can be\n\ 359b55d4692Sfgsch handled by one stub section. A negative value\n\ 360b55d4692Sfgsch locates all stubs before their branches (with a\n\ 361b55d4692Sfgsch group size of -N), while a positive value allows\n\ 362b55d4692Sfgsch two groups of input sections, one before, and one\n\ 363b55d4692Sfgsch after each stub section. Values of +/-1 indicate\n\ 364c074d1c9Sdrahn the linker should choose suitable defaults.\n" 365b55d4692Sfgsch )); 366b55d4692Sfgsch' 367b55d4692Sfgsch 368b55d4692SfgschPARSE_AND_LIST_ARGS_CASES=' 369b55d4692Sfgsch case OPTION_MULTI_SUBSPACE: 370b55d4692Sfgsch multi_subspace = 1; 371b55d4692Sfgsch break; 372b55d4692Sfgsch 373b55d4692Sfgsch case OPTION_STUBGROUP_SIZE: 374b55d4692Sfgsch { 375b55d4692Sfgsch const char *end; 376b55d4692Sfgsch group_size = bfd_scan_vma (optarg, &end, 0); 377b55d4692Sfgsch if (*end) 378b55d4692Sfgsch einfo (_("%P%F: invalid number `%s'\''\n"), optarg); 379b55d4692Sfgsch } 380b55d4692Sfgsch break; 381b55d4692Sfgsch' 382b55d4692Sfgsch 383b55d4692Sfgsch# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation 384b55d4692Sfgsch# 385b55d4692SfgschLDEMUL_AFTER_PARSE=hppaelf_after_parse 386c074d1c9SdrahnLDEMUL_FINISH=gld${EMULATION_NAME}_finish 387b55d4692SfgschLDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements 388