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