1214571Sdim# This shell script emits a C file. -*- C -*- 2214571Sdim# Copyright 2006 3214571Sdim# Free Software Foundation, Inc. 4214571Sdim# 5214571Sdim# This file is part of GLD, the Gnu Linker. 6214571Sdim# 7214571Sdim# This program is free software; you can redistribute it and/or modify 8214571Sdim# it under the terms of the GNU General Public License as published by 9214571Sdim# the Free Software Foundation; either version 2 of the License, or 10214571Sdim# (at your option) any later version. 11214571Sdim# 12214571Sdim# This program is distributed in the hope that it will be useful, 13214571Sdim# but WITHOUT ANY WARRANTY; without even the implied warranty of 14214571Sdim# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15214571Sdim# GNU General Public License for more details. 16214571Sdim# 17214571Sdim# You should have received a copy of the GNU General Public License 18214571Sdim# along with this program; if not, write to the Free Software 19214571Sdim# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20214571Sdim# MA 02110-1301 USA. 21214571Sdim 22214571Sdim# This file is sourced from elf32.em, and defines extra avr-elf 23214571Sdim# specific routines. It is used to generate the trampolines for the avr6 24214571Sdim# family devices where one needs to address the issue that it is not possible 25214571Sdim# to reach the whole program memory by using 16 bit pointers. 26214571Sdim 27214571Sdimcat >>e${EMULATION_NAME}.c <<EOF 28214571Sdim 29214571Sdim#include "elf32-avr.h" 30214571Sdim#include "ldctor.h" 31214571Sdim 32214571Sdim/* The fake file and it's corresponding section meant to hold 33214571Sdim the linker stubs if needed. */ 34214571Sdim 35214571Sdimstatic lang_input_statement_type *stub_file; 36214571Sdimstatic asection *avr_stub_section; 37214571Sdim 38214571Sdim/* Variables set by the command-line parameters and transfered 39214571Sdim to the bfd without use of global shared variables. */ 40214571Sdim 41214571Sdimstatic bfd_boolean avr_no_stubs = FALSE; 42214571Sdimstatic bfd_boolean avr_debug_relax = FALSE; 43214571Sdimstatic bfd_boolean avr_debug_stubs = FALSE; 44214571Sdimstatic bfd_boolean avr_replace_call_ret_sequences = TRUE; 45214571Sdimstatic bfd_vma avr_pc_wrap_around = 0x10000000; 46214571Sdim 47214571Sdim/* Transfers information to the bfd frontend. */ 48214571Sdim 49214571Sdimstatic void 50214571Sdimavr_elf_set_global_bfd_parameters (void) 51214571Sdim{ 52214571Sdim elf32_avr_setup_params (& link_info, 53214571Sdim stub_file->the_bfd, 54214571Sdim avr_stub_section, 55214571Sdim avr_no_stubs, 56214571Sdim avr_debug_stubs, 57214571Sdim avr_debug_relax, 58214571Sdim avr_pc_wrap_around, 59214571Sdim avr_replace_call_ret_sequences); 60214571Sdim} 61214571Sdim 62214571Sdim 63214571Sdim/* Makes a conservative estimate of the trampoline section size that could 64214571Sdim be corrected later on. */ 65214571Sdim 66214571Sdimstatic void 67214571Sdimavr_elf_${EMULATION_NAME}_before_allocation (void) 68214571Sdim{ 69214571Sdim int ret; 70214571Sdim 71214571Sdim gld${EMULATION_NAME}_before_allocation (); 72214571Sdim 73214571Sdim /* We only need stubs for the avr6 family. */ 74214571Sdim if (strcmp ("${EMULATION_NAME}","avr6")) 75214571Sdim avr_no_stubs = TRUE; 76214571Sdim 77214571Sdim avr_elf_set_global_bfd_parameters (); 78214571Sdim 79214571Sdim /* If generating a relocatable output file, then 80214571Sdim we don't have to generate the trampolines. */ 81214571Sdim if (link_info.relocatable) 82214571Sdim avr_no_stubs = TRUE; 83214571Sdim 84214571Sdim if (avr_no_stubs) 85214571Sdim return; 86214571Sdim 87214571Sdim ret = elf32_avr_setup_section_lists (output_bfd, &link_info); 88214571Sdim 89214571Sdim if (ret < 0) 90214571Sdim einfo ("%X%P: can not setup the input section list: %E\n"); 91214571Sdim 92214571Sdim if (ret <= 0) 93214571Sdim return; 94214571Sdim 95214571Sdim /* Call into the BFD backend to do the real "stub"-work. */ 96214571Sdim if (! elf32_avr_size_stubs (output_bfd, &link_info, TRUE)) 97214571Sdim einfo ("%X%P: can not size stub section: %E\n"); 98214571Sdim} 99214571Sdim 100214571Sdim/* This is called before the input files are opened. We create a new 101214571Sdim fake input file to hold the stub section and generate the section itself. */ 102214571Sdim 103214571Sdimstatic void 104214571Sdimavr_elf_create_output_section_statements (void) 105214571Sdim{ 106214571Sdim flagword flags; 107214571Sdim 108214571Sdim stub_file = lang_add_input_file ("linker stubs", 109214571Sdim lang_input_file_is_fake_enum, 110214571Sdim NULL); 111214571Sdim 112214571Sdim stub_file->the_bfd = bfd_create ("linker stubs", output_bfd); 113214571Sdim if (stub_file->the_bfd == NULL 114214571Sdim || !bfd_set_arch_mach (stub_file->the_bfd, 115214571Sdim bfd_get_arch (output_bfd), 116214571Sdim bfd_get_mach (output_bfd))) 117214571Sdim { 118214571Sdim einfo ("%X%P: can not create stub BFD %E\n"); 119214571Sdim return; 120214571Sdim } 121214571Sdim 122214571Sdim /* Now we add the stub section. */ 123214571Sdim 124214571Sdim avr_stub_section = bfd_make_section_anyway (stub_file->the_bfd, 125214571Sdim ".trampolines"); 126214571Sdim if (avr_stub_section == NULL) 127214571Sdim goto err_ret; 128214571Sdim 129214571Sdim flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE 130214571Sdim | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); 131214571Sdim if (!bfd_set_section_flags (stub_file->the_bfd, avr_stub_section, flags)) 132214571Sdim goto err_ret; 133214571Sdim 134214571Sdim avr_stub_section->alignment_power = 1; 135214571Sdim 136214571Sdim ldlang_add_file (stub_file); 137214571Sdim 138214571Sdim return; 139214571Sdim 140214571Sdim err_ret: 141214571Sdim einfo ("%X%P: can not make stub section: %E\n"); 142214571Sdim return; 143214571Sdim} 144214571Sdim 145214571Sdim/* Re-calculates the size of the stubs so that we won't waste space. */ 146214571Sdim 147214571Sdimstatic void 148214571Sdimavr_elf_finish (void) 149214571Sdim{ 150214571Sdim if (!avr_no_stubs) 151214571Sdim { 152214571Sdim /* Now build the linker stubs. */ 153214571Sdim if (stub_file->the_bfd->sections != NULL) 154214571Sdim { 155214571Sdim /* Call again the trampoline analyzer to initialize the trampoline 156214571Sdim stubs with the correct symbol addresses. Since there could have 157214571Sdim been relaxation, the symbol addresses that were found during 158214571Sdim first call may no longer be correct. */ 159214571Sdim if (!elf32_avr_size_stubs (output_bfd, &link_info, FALSE)) 160214571Sdim { 161214571Sdim einfo ("%X%P: can not size stub section: %E\n"); 162214571Sdim return; 163214571Sdim } 164214571Sdim 165214571Sdim if (!elf32_avr_build_stubs (&link_info)) 166214571Sdim einfo ("%X%P: can not build stubs: %E\n"); 167214571Sdim } 168214571Sdim } 169214571Sdim 170214571Sdim gld${EMULATION_NAME}_finish (); 171214571Sdim} 172214571Sdim 173214571Sdim 174214571SdimEOF 175214571Sdim 176214571Sdim 177214571SdimPARSE_AND_LIST_PROLOGUE=' 178214571Sdim 179214571Sdim#define OPTION_NO_CALL_RET_REPLACEMENT 301 180214571Sdim#define OPTION_PMEM_WRAP_AROUND 302 181214571Sdim#define OPTION_NO_STUBS 303 182214571Sdim#define OPTION_DEBUG_STUBS 304 183214571Sdim#define OPTION_DEBUG_RELAX 305 184214571Sdim' 185214571Sdim 186214571SdimPARSE_AND_LIST_LONGOPTS=' 187214571Sdim { "no-call-ret-replacement", no_argument, 188214571Sdim NULL, OPTION_NO_CALL_RET_REPLACEMENT}, 189214571Sdim { "pmem-wrap-around", required_argument, 190214571Sdim NULL, OPTION_PMEM_WRAP_AROUND}, 191214571Sdim { "no-stubs", no_argument, 192214571Sdim NULL, OPTION_NO_STUBS}, 193214571Sdim { "debug-stubs", no_argument, 194214571Sdim NULL, OPTION_DEBUG_STUBS}, 195214571Sdim { "debug-relax", no_argument, 196214571Sdim NULL, OPTION_DEBUG_RELAX}, 197214571Sdim' 198214571Sdim 199214571SdimPARSE_AND_LIST_OPTIONS=' 200214571Sdim fprintf (file, _(" --pmem-wrap-around=<val> " 201214571Sdim "Make the linker relaxation machine assume that a\n" 202214571Sdim " " 203214571Sdim "program counter wrap-around occures at address\n" 204214571Sdim " " 205214571Sdim "<val>. Supported values are 8k, 16k, 32k and 64k.\n")); 206214571Sdim fprintf (file, _(" --no-call-ret-replacement " 207214571Sdim "The relaxation machine normally will\n" 208214571Sdim " " 209214571Sdim "substitute two immediately following call/ret\n" 210214571Sdim " " 211214571Sdim "instructions by a single jump instruction.\n" 212214571Sdim " " 213214571Sdim "This option disables this optimization.\n")); 214214571Sdim fprintf (file, _(" --no-stubs " 215214571Sdim "If the linker detects to attempt to access\n" 216214571Sdim " " 217214571Sdim "an instruction beyond 128k by a reloc that\n" 218214571Sdim " " 219214571Sdim "is limited to 128k max, it inserts a jump\n" 220214571Sdim " " 221214571Sdim "stub. You can de-active this with this switch.\n")); 222214571Sdim fprintf (file, _(" --debug-stubs Used for debugging avr-ld.\n")); 223214571Sdim fprintf (file, _(" --debug-relax Used for debugging avr-ld.\n")); 224214571Sdim' 225214571Sdim 226214571SdimPARSE_AND_LIST_ARGS_CASES=' 227214571Sdim 228214571Sdim case OPTION_PMEM_WRAP_AROUND: 229214571Sdim { 230214571Sdim /* This variable is defined in the bfd library. */ 231214571Sdim if ((!strcmp (optarg,"32k")) || (!strcmp (optarg,"32K"))) 232214571Sdim avr_pc_wrap_around = 32768; 233214571Sdim else if ((!strcmp (optarg,"8k")) || (!strcmp (optarg,"8K"))) 234214571Sdim avr_pc_wrap_around = 8192; 235214571Sdim else if ((!strcmp (optarg,"16k")) || (!strcmp (optarg,"16K"))) 236214571Sdim avr_pc_wrap_around = 16384; 237214571Sdim else if ((!strcmp (optarg,"64k")) || (!strcmp (optarg,"64K"))) 238214571Sdim avr_pc_wrap_around = 0x10000; 239214571Sdim else 240214571Sdim return FALSE; 241214571Sdim } 242214571Sdim break; 243214571Sdim 244214571Sdim case OPTION_DEBUG_STUBS: 245214571Sdim avr_debug_stubs = TRUE; 246214571Sdim break; 247214571Sdim 248214571Sdim case OPTION_DEBUG_RELAX: 249214571Sdim avr_debug_relax = TRUE; 250214571Sdim break; 251214571Sdim 252214571Sdim case OPTION_NO_STUBS: 253214571Sdim avr_no_stubs = TRUE; 254214571Sdim break; 255214571Sdim 256214571Sdim case OPTION_NO_CALL_RET_REPLACEMENT: 257214571Sdim { 258214571Sdim /* This variable is defined in the bfd library. */ 259214571Sdim avr_replace_call_ret_sequences = FALSE; 260214571Sdim } 261214571Sdim break; 262214571Sdim' 263214571Sdim 264214571Sdim# 265214571Sdim# Put these extra avr-elf routines in ld_${EMULATION_NAME}_emulation 266214571Sdim# 267214571SdimLDEMUL_BEFORE_ALLOCATION=avr_elf_${EMULATION_NAME}_before_allocation 268214571SdimLDEMUL_FINISH=avr_elf_finish 269214571SdimLDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=avr_elf_create_output_section_statements 270