1# This shell script emits a C file. -*- C -*- 2# Copyright (C) 1991-2016 Free Software Foundation, Inc. 3# 4# This file is part of the GNU Binutils. 5# 6# This program is free software; you can redistribute it and/or modify 7# it under the terms of the GNU General Public License as published by 8# the Free Software Foundation; either version 3 of the License, or 9# (at your option) any later version. 10# 11# This program is distributed in the hope that it will be useful, 12# but WITHOUT ANY WARRANTY; without even the implied warranty of 13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14# GNU General Public License for more details. 15# 16# You should have received a copy of the GNU General Public License 17# along with this program; if not, write to the Free Software 18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 19# MA 02110-1301, USA. 20# 21 22# This file is sourced from elf32.em, and defines extra hppa-elf 23# specific routines. 24# 25fragment <<EOF 26 27#include "ldctor.h" 28#include "elf32-hppa.h" 29 30 31/* Fake input file for stubs. */ 32static lang_input_statement_type *stub_file; 33 34/* Type of import/export stubs to build. For a single sub-space model, 35 we can build smaller import stubs and there is no need for export 36 stubs. */ 37static int multi_subspace = 0; 38 39/* Whether we need to call hppa_layout_sections_again. */ 40static int need_laying_out = 0; 41 42/* Maximum size of a group of input sections that can be handled by 43 one stub section. A value of +/-1 indicates the bfd back-end 44 should use a suitable default size. */ 45static bfd_signed_vma group_size = 1; 46 47/* Stops the linker merging .text sections on a relocatable link, 48 and adds millicode library to the list of input files. */ 49 50static void 51hppaelf_after_parse (void) 52{ 53 if (bfd_link_relocatable (&link_info)) 54 lang_add_unique (".text"); 55 56 /* Enable this once we split millicode stuff from libgcc: 57 lang_add_input_file ("milli", 58 lang_input_file_is_l_enum, 59 NULL); 60 */ 61 62 gld${EMULATION_NAME}_after_parse (); 63} 64 65/* This is called before the input files are opened. We create a new 66 fake input file to hold the stub sections. */ 67 68static void 69hppaelf_create_output_section_statements (void) 70{ 71 if (!(bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour 72 && (elf_object_id (link_info.output_bfd) == HPPA32_ELF_DATA 73 || elf_object_id (link_info.output_bfd) == HPPA64_ELF_DATA))) 74 return; 75 76 stub_file = lang_add_input_file ("linker stubs", 77 lang_input_file_is_fake_enum, 78 NULL); 79 stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd); 80 if (stub_file->the_bfd == NULL 81 || ! bfd_set_arch_mach (stub_file->the_bfd, 82 bfd_get_arch (link_info.output_bfd), 83 bfd_get_mach (link_info.output_bfd))) 84 { 85 einfo ("%X%P: can not create BFD %E\n"); 86 return; 87 } 88 89 stub_file->the_bfd->flags |= BFD_LINKER_CREATED; 90 ldlang_add_file (stub_file); 91 elf32_hppa_init_stub_bfd (stub_file->the_bfd, &link_info); 92} 93 94 95struct hook_stub_info 96{ 97 lang_statement_list_type add; 98 asection *input_section; 99}; 100 101/* Traverse the linker tree to find the spot where the stub goes. */ 102 103static bfd_boolean 104hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp) 105{ 106 lang_statement_union_type *l; 107 bfd_boolean ret; 108 109 for (; (l = *lp) != NULL; lp = &l->header.next) 110 { 111 switch (l->header.type) 112 { 113 case lang_constructors_statement_enum: 114 ret = hook_in_stub (info, &constructor_list.head); 115 if (ret) 116 return ret; 117 break; 118 119 case lang_output_section_statement_enum: 120 ret = hook_in_stub (info, 121 &l->output_section_statement.children.head); 122 if (ret) 123 return ret; 124 break; 125 126 case lang_wild_statement_enum: 127 ret = hook_in_stub (info, &l->wild_statement.children.head); 128 if (ret) 129 return ret; 130 break; 131 132 case lang_group_statement_enum: 133 ret = hook_in_stub (info, &l->group_statement.children.head); 134 if (ret) 135 return ret; 136 break; 137 138 case lang_input_section_enum: 139 if (l->input_section.section == info->input_section) 140 { 141 /* We've found our section. Insert the stub immediately 142 before its associated input section. */ 143 *lp = info->add.head; 144 *(info->add.tail) = l; 145 return TRUE; 146 } 147 break; 148 149 case lang_data_statement_enum: 150 case lang_reloc_statement_enum: 151 case lang_object_symbols_statement_enum: 152 case lang_output_statement_enum: 153 case lang_target_statement_enum: 154 case lang_input_statement_enum: 155 case lang_assignment_statement_enum: 156 case lang_padding_statement_enum: 157 case lang_address_statement_enum: 158 case lang_fill_statement_enum: 159 break; 160 161 default: 162 FAIL (); 163 break; 164 } 165 } 166 return FALSE; 167} 168 169 170/* Call-back for elf32_hppa_size_stubs. */ 171 172/* Create a new stub section, and arrange for it to be linked 173 immediately before INPUT_SECTION. */ 174 175static asection * 176hppaelf_add_stub_section (const char *stub_sec_name, asection *input_section) 177{ 178 asection *stub_sec; 179 flagword flags; 180 asection *output_section; 181 lang_output_section_statement_type *os; 182 struct hook_stub_info info; 183 184 flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE 185 | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); 186 stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd, 187 stub_sec_name, flags); 188 if (stub_sec == NULL) 189 goto err_ret; 190 191 output_section = input_section->output_section; 192 os = lang_output_section_get (output_section); 193 194 info.input_section = input_section; 195 lang_list_init (&info.add); 196 lang_add_section (&info.add, stub_sec, NULL, os); 197 198 if (info.add.head == NULL) 199 goto err_ret; 200 201 if (hook_in_stub (&info, &os->children.head)) 202 return stub_sec; 203 204 err_ret: 205 einfo ("%X%P: can not make stub section: %E\n"); 206 return NULL; 207} 208 209 210/* Another call-back for elf32_hppa_size_stubs. */ 211 212static void 213hppaelf_layout_sections_again (void) 214{ 215 /* If we have changed sizes of the stub sections, then we need 216 to recalculate all the section offsets. This may mean we need to 217 add even more stubs. */ 218 gld${EMULATION_NAME}_map_segments (TRUE); 219 need_laying_out = -1; 220} 221 222 223static void 224build_section_lists (lang_statement_union_type *statement) 225{ 226 if (statement->header.type == lang_input_section_enum) 227 { 228 asection *i = statement->input_section.section; 229 230 if (i->sec_info_type != SEC_INFO_TYPE_JUST_SYMS 231 && (i->flags & SEC_EXCLUDE) == 0 232 && i->output_section != NULL 233 && i->output_section->owner == link_info.output_bfd) 234 { 235 elf32_hppa_next_input_section (&link_info, i); 236 } 237 } 238} 239 240 241/* For the PA we use this opportunity to size and build linker stubs. */ 242 243static void 244gld${EMULATION_NAME}_after_allocation (void) 245{ 246 int ret; 247 248 /* bfd_elf_discard_info just plays with data and debugging sections, 249 ie. doesn't affect code size, so we can delay resizing the 250 sections. It's likely we'll resize everything in the process of 251 adding stubs. */ 252 ret = bfd_elf_discard_info (link_info.output_bfd, &link_info); 253 if (ret < 0) 254 { 255 einfo ("%X%P: .eh_frame/.stab edit: %E\n"); 256 return; 257 } 258 else if (ret > 0) 259 need_laying_out = 1; 260 261 /* If generating a relocatable output file, then we don't 262 have to examine the relocs. */ 263 if (stub_file != NULL && !bfd_link_relocatable (&link_info)) 264 { 265 ret = elf32_hppa_setup_section_lists (link_info.output_bfd, &link_info); 266 if (ret != 0) 267 { 268 if (ret < 0) 269 { 270 einfo ("%X%P: can not size stub section: %E\n"); 271 return; 272 } 273 274 lang_for_each_statement (build_section_lists); 275 276 /* Call into the BFD backend to do the real work. */ 277 if (! elf32_hppa_size_stubs (link_info.output_bfd, 278 stub_file->the_bfd, 279 &link_info, 280 multi_subspace, 281 group_size, 282 &hppaelf_add_stub_section, 283 &hppaelf_layout_sections_again)) 284 { 285 einfo ("%X%P: can not size stub section: %E\n"); 286 return; 287 } 288 } 289 } 290 291 if (need_laying_out != -1) 292 gld${EMULATION_NAME}_map_segments (need_laying_out); 293 294 if (!bfd_link_relocatable (&link_info)) 295 { 296 /* Set the global data pointer. */ 297 if (! elf32_hppa_set_gp (link_info.output_bfd, &link_info)) 298 { 299 einfo ("%X%P: can not set gp\n"); 300 return; 301 } 302 303 /* Now build the linker stubs. */ 304 if (stub_file != NULL && stub_file->the_bfd->sections != NULL) 305 { 306 if (! elf32_hppa_build_stubs (&link_info)) 307 einfo ("%X%P: can not build stubs: %E\n"); 308 } 309 } 310} 311 312 313/* Avoid processing the fake stub_file in vercheck, stat_needed and 314 check_needed routines. */ 315 316static void (*real_func) (lang_input_statement_type *); 317 318static void hppa_for_each_input_file_wrapper (lang_input_statement_type *l) 319{ 320 if (l != stub_file) 321 (*real_func) (l); 322} 323 324static void 325hppa_lang_for_each_input_file (void (*func) (lang_input_statement_type *)) 326{ 327 real_func = func; 328 lang_for_each_input_file (&hppa_for_each_input_file_wrapper); 329} 330 331#define lang_for_each_input_file hppa_lang_for_each_input_file 332 333EOF 334 335# Define some shell vars to insert bits of code into the standard elf 336# parse_args and list_options functions. 337# 338PARSE_AND_LIST_PROLOGUE=' 339#define OPTION_MULTI_SUBSPACE 301 340#define OPTION_STUBGROUP_SIZE (OPTION_MULTI_SUBSPACE + 1) 341' 342 343PARSE_AND_LIST_LONGOPTS=' 344 { "multi-subspace", no_argument, NULL, OPTION_MULTI_SUBSPACE }, 345 { "stub-group-size", required_argument, NULL, OPTION_STUBGROUP_SIZE }, 346' 347 348PARSE_AND_LIST_OPTIONS=' 349 fprintf (file, _("\ 350 --multi-subspace Generate import and export stubs to support\n\ 351 multiple sub-space shared libraries\n" 352 )); 353 fprintf (file, _("\ 354 --stub-group-size=N Maximum size of a group of input sections that\n\ 355 can be handled by one stub section. A negative\n\ 356 value locates all stubs before their branches\n\ 357 (with a group size of -N), while a positive\n\ 358 value allows two groups of input sections, one\n\ 359 before, and one after each stub section.\n\ 360 Values of +/-1 indicate the linker should\n\ 361 choose suitable defaults.\n" 362 )); 363' 364 365PARSE_AND_LIST_ARGS_CASES=' 366 case OPTION_MULTI_SUBSPACE: 367 multi_subspace = 1; 368 break; 369 370 case OPTION_STUBGROUP_SIZE: 371 { 372 const char *end; 373 group_size = bfd_scan_vma (optarg, &end, 0); 374 if (*end) 375 einfo (_("%P%F: invalid number `%s'\''\n"), optarg); 376 } 377 break; 378' 379 380# Put these extra hppaelf routines in ld_${EMULATION_NAME}_emulation 381# 382LDEMUL_AFTER_PARSE=hppaelf_after_parse 383LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation 384LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=hppaelf_create_output_section_statements 385