1# This shell script emits a C file. -*- C -*- 2# Copyright 2006 3# Free Software Foundation, Inc. 4# 5# This file is part of GLD, the Gnu Linker. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20# MA 02110-1301 USA. 21 22# This file is sourced from elf32.em, and defines extra avr-elf 23# specific routines. It is used to generate the trampolines for the avr6 24# family devices where one needs to address the issue that it is not possible 25# to reach the whole program memory by using 16 bit pointers. 26 27cat >>e${EMULATION_NAME}.c <<EOF 28 29#include "elf32-avr.h" 30#include "ldctor.h" 31 32/* The fake file and it's corresponding section meant to hold 33 the linker stubs if needed. */ 34 35static lang_input_statement_type *stub_file; 36static asection *avr_stub_section; 37 38/* Variables set by the command-line parameters and transfered 39 to the bfd without use of global shared variables. */ 40 41static bfd_boolean avr_no_stubs = FALSE; 42static bfd_boolean avr_debug_relax = FALSE; 43static bfd_boolean avr_debug_stubs = FALSE; 44static bfd_boolean avr_replace_call_ret_sequences = TRUE; 45static bfd_vma avr_pc_wrap_around = 0x10000000; 46 47/* Transfers information to the bfd frontend. */ 48 49static void 50avr_elf_set_global_bfd_parameters (void) 51{ 52 elf32_avr_setup_params (& link_info, 53 stub_file->the_bfd, 54 avr_stub_section, 55 avr_no_stubs, 56 avr_debug_stubs, 57 avr_debug_relax, 58 avr_pc_wrap_around, 59 avr_replace_call_ret_sequences); 60} 61 62 63/* Makes a conservative estimate of the trampoline section size that could 64 be corrected later on. */ 65 66static void 67avr_elf_${EMULATION_NAME}_before_allocation (void) 68{ 69 int ret; 70 71 gld${EMULATION_NAME}_before_allocation (); 72 73 /* We only need stubs for the avr6 family. */ 74 if (strcmp ("${EMULATION_NAME}","avr6")) 75 avr_no_stubs = TRUE; 76 77 avr_elf_set_global_bfd_parameters (); 78 79 /* If generating a relocatable output file, then 80 we don't have to generate the trampolines. */ 81 if (link_info.relocatable) 82 avr_no_stubs = TRUE; 83 84 if (avr_no_stubs) 85 return; 86 87 ret = elf32_avr_setup_section_lists (output_bfd, &link_info); 88 89 if (ret < 0) 90 einfo ("%X%P: can not setup the input section list: %E\n"); 91 92 if (ret <= 0) 93 return; 94 95 /* Call into the BFD backend to do the real "stub"-work. */ 96 if (! elf32_avr_size_stubs (output_bfd, &link_info, TRUE)) 97 einfo ("%X%P: can not size stub section: %E\n"); 98} 99 100/* This is called before the input files are opened. We create a new 101 fake input file to hold the stub section and generate the section itself. */ 102 103static void 104avr_elf_create_output_section_statements (void) 105{ 106 flagword flags; 107 108 stub_file = lang_add_input_file ("linker stubs", 109 lang_input_file_is_fake_enum, 110 NULL); 111 112 stub_file->the_bfd = bfd_create ("linker stubs", output_bfd); 113 if (stub_file->the_bfd == NULL 114 || !bfd_set_arch_mach (stub_file->the_bfd, 115 bfd_get_arch (output_bfd), 116 bfd_get_mach (output_bfd))) 117 { 118 einfo ("%X%P: can not create stub BFD %E\n"); 119 return; 120 } 121 122 /* Now we add the stub section. */ 123 124 avr_stub_section = bfd_make_section_anyway (stub_file->the_bfd, 125 ".trampolines"); 126 if (avr_stub_section == NULL) 127 goto err_ret; 128 129 flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE 130 | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); 131 if (!bfd_set_section_flags (stub_file->the_bfd, avr_stub_section, flags)) 132 goto err_ret; 133 134 avr_stub_section->alignment_power = 1; 135 136 ldlang_add_file (stub_file); 137 138 return; 139 140 err_ret: 141 einfo ("%X%P: can not make stub section: %E\n"); 142 return; 143} 144 145/* Re-calculates the size of the stubs so that we won't waste space. */ 146 147static void 148avr_elf_finish (void) 149{ 150 if (!avr_no_stubs) 151 { 152 /* Now build the linker stubs. */ 153 if (stub_file->the_bfd->sections != NULL) 154 { 155 /* Call again the trampoline analyzer to initialize the trampoline 156 stubs with the correct symbol addresses. Since there could have 157 been relaxation, the symbol addresses that were found during 158 first call may no longer be correct. */ 159 if (!elf32_avr_size_stubs (output_bfd, &link_info, FALSE)) 160 { 161 einfo ("%X%P: can not size stub section: %E\n"); 162 return; 163 } 164 165 if (!elf32_avr_build_stubs (&link_info)) 166 einfo ("%X%P: can not build stubs: %E\n"); 167 } 168 } 169 170 gld${EMULATION_NAME}_finish (); 171} 172 173 174EOF 175 176 177PARSE_AND_LIST_PROLOGUE=' 178 179#define OPTION_NO_CALL_RET_REPLACEMENT 301 180#define OPTION_PMEM_WRAP_AROUND 302 181#define OPTION_NO_STUBS 303 182#define OPTION_DEBUG_STUBS 304 183#define OPTION_DEBUG_RELAX 305 184' 185 186PARSE_AND_LIST_LONGOPTS=' 187 { "no-call-ret-replacement", no_argument, 188 NULL, OPTION_NO_CALL_RET_REPLACEMENT}, 189 { "pmem-wrap-around", required_argument, 190 NULL, OPTION_PMEM_WRAP_AROUND}, 191 { "no-stubs", no_argument, 192 NULL, OPTION_NO_STUBS}, 193 { "debug-stubs", no_argument, 194 NULL, OPTION_DEBUG_STUBS}, 195 { "debug-relax", no_argument, 196 NULL, OPTION_DEBUG_RELAX}, 197' 198 199PARSE_AND_LIST_OPTIONS=' 200 fprintf (file, _(" --pmem-wrap-around=<val> " 201 "Make the linker relaxation machine assume that a\n" 202 " " 203 "program counter wrap-around occures at address\n" 204 " " 205 "<val>. Supported values are 8k, 16k, 32k and 64k.\n")); 206 fprintf (file, _(" --no-call-ret-replacement " 207 "The relaxation machine normally will\n" 208 " " 209 "substitute two immediately following call/ret\n" 210 " " 211 "instructions by a single jump instruction.\n" 212 " " 213 "This option disables this optimization.\n")); 214 fprintf (file, _(" --no-stubs " 215 "If the linker detects to attempt to access\n" 216 " " 217 "an instruction beyond 128k by a reloc that\n" 218 " " 219 "is limited to 128k max, it inserts a jump\n" 220 " " 221 "stub. You can de-active this with this switch.\n")); 222 fprintf (file, _(" --debug-stubs Used for debugging avr-ld.\n")); 223 fprintf (file, _(" --debug-relax Used for debugging avr-ld.\n")); 224' 225 226PARSE_AND_LIST_ARGS_CASES=' 227 228 case OPTION_PMEM_WRAP_AROUND: 229 { 230 /* This variable is defined in the bfd library. */ 231 if ((!strcmp (optarg,"32k")) || (!strcmp (optarg,"32K"))) 232 avr_pc_wrap_around = 32768; 233 else if ((!strcmp (optarg,"8k")) || (!strcmp (optarg,"8K"))) 234 avr_pc_wrap_around = 8192; 235 else if ((!strcmp (optarg,"16k")) || (!strcmp (optarg,"16K"))) 236 avr_pc_wrap_around = 16384; 237 else if ((!strcmp (optarg,"64k")) || (!strcmp (optarg,"64K"))) 238 avr_pc_wrap_around = 0x10000; 239 else 240 return FALSE; 241 } 242 break; 243 244 case OPTION_DEBUG_STUBS: 245 avr_debug_stubs = TRUE; 246 break; 247 248 case OPTION_DEBUG_RELAX: 249 avr_debug_relax = TRUE; 250 break; 251 252 case OPTION_NO_STUBS: 253 avr_no_stubs = TRUE; 254 break; 255 256 case OPTION_NO_CALL_RET_REPLACEMENT: 257 { 258 /* This variable is defined in the bfd library. */ 259 avr_replace_call_ret_sequences = FALSE; 260 } 261 break; 262' 263 264# 265# Put these extra avr-elf routines in ld_${EMULATION_NAME}_emulation 266# 267LDEMUL_BEFORE_ALLOCATION=avr_elf_${EMULATION_NAME}_before_allocation 268LDEMUL_FINISH=avr_elf_finish 269LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=avr_elf_create_output_section_statements 270