]>
Commit | Line | Data |
---|---|---|
28c9d252 | 1 | # This shell script emits a C file. -*- C -*- |
250d07de | 2 | # Copyright (C) 2006-2021 Free Software Foundation, Inc. |
28c9d252 | 3 | # |
f96b4a7b | 4 | # This file is part of the GNU Binutils. |
28c9d252 NC |
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 | |
f96b4a7b | 8 | # the Free Software Foundation; either version 3 of the License, or |
28c9d252 NC |
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 | |
f96b4a7b NC |
18 | # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | # MA 02110-1301, USA. | |
28c9d252 | 20 | |
f96b4a7b | 21 | |
075a2b89 | 22 | # This file is sourced from elf.em, and defines extra avr-elf specific |
f96b4a7b NC |
23 | # routines. It is used to generate the trampolines for the avr6 family |
24 | # of devices where one needs to address the issue that it is not possible | |
28c9d252 NC |
25 | # to reach the whole program memory by using 16 bit pointers. |
26 | ||
92b93329 | 27 | fragment <<EOF |
28c9d252 NC |
28 | |
29 | #include "elf32-avr.h" | |
30 | #include "ldctor.h" | |
9d7b48dc | 31 | #include "elf/avr.h" |
28c9d252 | 32 | |
92b93329 | 33 | /* The fake file and it's corresponding section meant to hold |
28c9d252 NC |
34 | the linker stubs if needed. */ |
35 | ||
36 | static lang_input_statement_type *stub_file; | |
37 | static asection *avr_stub_section; | |
38 | ||
839b0b3f | 39 | /* Variables set by the command-line parameters and transferred |
28c9d252 NC |
40 | to the bfd without use of global shared variables. */ |
41 | ||
f38a2680 AM |
42 | static bool avr_no_stubs = false; |
43 | static bool avr_debug_relax = false; | |
44 | static bool avr_debug_stubs = false; | |
45 | static bool avr_replace_call_ret_sequences = true; | |
28c9d252 NC |
46 | static bfd_vma avr_pc_wrap_around = 0x10000000; |
47 | ||
48 | /* Transfers information to the bfd frontend. */ | |
49 | ||
50 | static void | |
51 | avr_elf_set_global_bfd_parameters (void) | |
52 | { | |
53 | elf32_avr_setup_params (& link_info, | |
6c19b93b AM |
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); | |
28c9d252 NC |
61 | } |
62 | ||
63 | ||
64 | /* Makes a conservative estimate of the trampoline section size that could | |
65 | be corrected later on. */ | |
66 | ||
67 | static void | |
68 | avr_elf_${EMULATION_NAME}_before_allocation (void) | |
69 | { | |
70 | int ret; | |
71 | ||
72 | gld${EMULATION_NAME}_before_allocation (); | |
73 | ||
fd9770d8 NC |
74 | if (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour) |
75 | { | |
f38a2680 | 76 | avr_no_stubs = true; |
fd9770d8 NC |
77 | return; |
78 | } | |
79 | ||
6ba2ed48 NC |
80 | /* We only need stubs for avr6, avrxmega6, and avrxmega7. */ |
81 | if (strcmp ("${EMULATION_NAME}", "avr6") != 0 | |
82 | && strcmp ("${EMULATION_NAME}", "avrxmega6") != 0 | |
83 | && strcmp ("${EMULATION_NAME}", "avrxmega7") != 0) | |
f38a2680 | 84 | avr_no_stubs = true; |
28c9d252 NC |
85 | |
86 | avr_elf_set_global_bfd_parameters (); | |
87 | ||
88 | /* If generating a relocatable output file, then | |
89 | we don't have to generate the trampolines. */ | |
0e1862bb | 90 | if (bfd_link_relocatable (&link_info)) |
f38a2680 | 91 | avr_no_stubs = true; |
28c9d252 NC |
92 | |
93 | if (avr_no_stubs) | |
94 | return; | |
95 | ||
f13a99db | 96 | ret = elf32_avr_setup_section_lists (link_info.output_bfd, &link_info); |
28c9d252 NC |
97 | |
98 | if (ret < 0) | |
d003af55 | 99 | einfo (_("%X%P: can not setup the input section list: %E\n")); |
28c9d252 NC |
100 | |
101 | if (ret <= 0) | |
102 | return; | |
103 | ||
104 | /* Call into the BFD backend to do the real "stub"-work. */ | |
f38a2680 | 105 | if (! elf32_avr_size_stubs (link_info.output_bfd, &link_info, true)) |
d003af55 | 106 | einfo (_("%X%P: can not size stub section: %E\n")); |
28c9d252 NC |
107 | } |
108 | ||
109 | /* This is called before the input files are opened. We create a new | |
110 | fake input file to hold the stub section and generate the section itself. */ | |
111 | ||
112 | static void | |
113 | avr_elf_create_output_section_statements (void) | |
114 | { | |
115 | flagword flags; | |
116 | ||
fd9770d8 NC |
117 | if (bfd_get_flavour (link_info.output_bfd) != bfd_target_elf_flavour) |
118 | { | |
df5f2391 AM |
119 | einfo (_("%F%P: error: cannot change output format " |
120 | "whilst linking %s binaries\n"), "AVR"); | |
fd9770d8 NC |
121 | return; |
122 | } | |
123 | ||
28c9d252 | 124 | stub_file = lang_add_input_file ("linker stubs", |
6c19b93b AM |
125 | lang_input_file_is_fake_enum, |
126 | NULL); | |
28c9d252 | 127 | |
f13a99db | 128 | stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd); |
28c9d252 NC |
129 | if (stub_file->the_bfd == NULL |
130 | || !bfd_set_arch_mach (stub_file->the_bfd, | |
6c19b93b AM |
131 | bfd_get_arch (link_info.output_bfd), |
132 | bfd_get_mach (link_info.output_bfd))) | |
28c9d252 | 133 | { |
df5f2391 | 134 | einfo (_("%X%P: can not create stub BFD: %E\n")); |
28c9d252 NC |
135 | return; |
136 | } | |
137 | ||
138 | /* Now we add the stub section. */ | |
139 | ||
28c9d252 | 140 | flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE |
6c19b93b | 141 | | SEC_HAS_CONTENTS | SEC_RELOC | SEC_IN_MEMORY | SEC_KEEP); |
9795b468 AM |
142 | avr_stub_section = bfd_make_section_anyway_with_flags (stub_file->the_bfd, |
143 | ".trampolines", | |
144 | flags); | |
145 | if (avr_stub_section == NULL) | |
28c9d252 NC |
146 | goto err_ret; |
147 | ||
148 | avr_stub_section->alignment_power = 1; | |
92b93329 | 149 | |
28c9d252 NC |
150 | ldlang_add_file (stub_file); |
151 | ||
152 | return; | |
153 | ||
6c19b93b AM |
154 | err_ret: |
155 | einfo (_("%X%P: can not make stub section: %E\n")); | |
156 | return; | |
28c9d252 NC |
157 | } |
158 | ||
159 | /* Re-calculates the size of the stubs so that we won't waste space. */ | |
160 | ||
161 | static void | |
eaeb0a9d | 162 | avr_elf_after_allocation (void) |
92b93329 | 163 | { |
28d5f677 | 164 | if (!avr_no_stubs && ! RELAXATION_ENABLED) |
28c9d252 | 165 | { |
eaeb0a9d AM |
166 | /* If relaxing, elf32_avr_size_stubs will be called from |
167 | elf32_avr_relax_section. */ | |
f38a2680 | 168 | if (!elf32_avr_size_stubs (link_info.output_bfd, &link_info, true)) |
d003af55 | 169 | einfo (_("%X%P: can not size stub section: %E\n")); |
28c9d252 NC |
170 | } |
171 | ||
eaeb0a9d AM |
172 | gld${EMULATION_NAME}_after_allocation (); |
173 | ||
174 | /* Now build the linker stubs. */ | |
175 | if (!avr_no_stubs) | |
176 | { | |
177 | if (!elf32_avr_build_stubs (&link_info)) | |
d003af55 | 178 | einfo (_("%X%P: can not build stubs: %E\n")); |
eaeb0a9d | 179 | } |
28c9d252 NC |
180 | } |
181 | ||
4d4ef6fd AM |
182 | static void |
183 | avr_elf_before_parse (void) | |
184 | { | |
185 | /* Don't create a demand-paged executable, since this feature isn't | |
186 | meaningful in AVR. */ | |
f38a2680 | 187 | config.magic_demand_paged = false; |
4d4ef6fd AM |
188 | |
189 | gld${EMULATION_NAME}_before_parse (); | |
190 | } | |
28c9d252 | 191 | |
9d7b48dc AB |
192 | static void |
193 | avr_finish (void) | |
194 | { | |
195 | bfd *abfd; | |
f38a2680 | 196 | bool avr_link_relax; |
9d7b48dc | 197 | |
0e1862bb | 198 | if (bfd_link_relocatable (&link_info)) |
9d7b48dc | 199 | { |
f38a2680 | 200 | avr_link_relax = true; |
9d7b48dc | 201 | for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link.next) |
6c19b93b AM |
202 | { |
203 | /* Don't let the linker stubs prevent the final object being | |
204 | marked as link-relax ready. */ | |
205 | if ((elf_elfheader (abfd)->e_flags | |
206 | & EF_AVR_LINKRELAX_PREPARED) == 0 | |
207 | && abfd != stub_file->the_bfd) | |
208 | { | |
f38a2680 | 209 | avr_link_relax = false; |
6c19b93b AM |
210 | break; |
211 | } | |
212 | } | |
9d7b48dc AB |
213 | } |
214 | else | |
215 | { | |
216 | avr_link_relax = RELAXATION_ENABLED; | |
217 | } | |
218 | ||
219 | abfd = link_info.output_bfd; | |
fd9770d8 NC |
220 | |
221 | if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) | |
222 | { | |
223 | if (avr_link_relax) | |
224 | elf_elfheader (abfd)->e_flags |= EF_AVR_LINKRELAX_PREPARED; | |
225 | else | |
226 | elf_elfheader (abfd)->e_flags &= ~EF_AVR_LINKRELAX_PREPARED; | |
227 | } | |
9d7b48dc AB |
228 | |
229 | finish_default (); | |
230 | } | |
28c9d252 NC |
231 | EOF |
232 | ||
233 | ||
234 | PARSE_AND_LIST_PROLOGUE=' | |
235 | ||
236 | #define OPTION_NO_CALL_RET_REPLACEMENT 301 | |
6c19b93b AM |
237 | #define OPTION_PMEM_WRAP_AROUND 302 |
238 | #define OPTION_NO_STUBS 303 | |
239 | #define OPTION_DEBUG_STUBS 304 | |
240 | #define OPTION_DEBUG_RELAX 305 | |
28c9d252 NC |
241 | ' |
242 | ||
243 | PARSE_AND_LIST_LONGOPTS=' | |
92b93329 | 244 | { "no-call-ret-replacement", no_argument, |
6c19b93b | 245 | NULL, OPTION_NO_CALL_RET_REPLACEMENT}, |
92b93329 | 246 | { "pmem-wrap-around", required_argument, |
28c9d252 | 247 | NULL, OPTION_PMEM_WRAP_AROUND}, |
92b93329 | 248 | { "no-stubs", no_argument, |
28c9d252 | 249 | NULL, OPTION_NO_STUBS}, |
92b93329 | 250 | { "debug-stubs", no_argument, |
28c9d252 | 251 | NULL, OPTION_DEBUG_STUBS}, |
92b93329 | 252 | { "debug-relax", no_argument, |
28c9d252 NC |
253 | NULL, OPTION_DEBUG_RELAX}, |
254 | ' | |
255 | ||
256 | PARSE_AND_LIST_OPTIONS=' | |
442996ee AM |
257 | fprintf (file, _(" --pmem-wrap-around=<val> " |
258 | "Make the linker relaxation machine assume that a\n" | |
259 | " " | |
eca4b721 | 260 | " program counter wrap-around occurs at address\n" |
442996ee AM |
261 | " " |
262 | " <val>. Supported values: 8k, 16k, 32k and 64k.\n")); | |
263 | fprintf (file, _(" --no-call-ret-replacement " | |
264 | "The relaxation machine normally will\n" | |
265 | " " | |
266 | " substitute two immediately following call/ret\n" | |
267 | " " | |
268 | " instructions by a single jump instruction.\n" | |
269 | " " | |
270 | " This option disables this optimization.\n")); | |
271 | fprintf (file, _(" --no-stubs " | |
272 | "If the linker detects to attempt to access\n" | |
273 | " " | |
274 | " an instruction beyond 128k by a reloc that\n" | |
275 | " " | |
276 | " is limited to 128k max, it inserts a jump\n" | |
277 | " " | |
278 | " stub. You can de-active this with this switch.\n")); | |
279 | fprintf (file, _(" --debug-stubs " | |
280 | "Used for debugging avr-ld.\n")); | |
281 | fprintf (file, _(" --debug-relax " | |
282 | "Used for debugging avr-ld.\n")); | |
28c9d252 NC |
283 | ' |
284 | ||
285 | PARSE_AND_LIST_ARGS_CASES=' | |
286 | ||
287 | case OPTION_PMEM_WRAP_AROUND: | |
92b93329 | 288 | { |
6c19b93b AM |
289 | /* This variable is defined in the bfd library. */ |
290 | if ((!strcmp (optarg,"32k")) || (!strcmp (optarg,"32K"))) | |
291 | avr_pc_wrap_around = 32768; | |
292 | else if ((!strcmp (optarg,"8k")) || (!strcmp (optarg,"8K"))) | |
293 | avr_pc_wrap_around = 8192; | |
294 | else if ((!strcmp (optarg,"16k")) || (!strcmp (optarg,"16K"))) | |
295 | avr_pc_wrap_around = 16384; | |
296 | else if ((!strcmp (optarg,"64k")) || (!strcmp (optarg,"64K"))) | |
297 | avr_pc_wrap_around = 0x10000; | |
298 | else | |
f38a2680 | 299 | return false; |
28c9d252 NC |
300 | } |
301 | break; | |
302 | ||
303 | case OPTION_DEBUG_STUBS: | |
f38a2680 | 304 | avr_debug_stubs = true; |
28c9d252 NC |
305 | break; |
306 | ||
307 | case OPTION_DEBUG_RELAX: | |
f38a2680 | 308 | avr_debug_relax = true; |
28c9d252 NC |
309 | break; |
310 | ||
311 | case OPTION_NO_STUBS: | |
f38a2680 | 312 | avr_no_stubs = true; |
28c9d252 NC |
313 | break; |
314 | ||
315 | case OPTION_NO_CALL_RET_REPLACEMENT: | |
316 | { | |
6c19b93b | 317 | /* This variable is defined in the bfd library. */ |
f38a2680 | 318 | avr_replace_call_ret_sequences = false; |
28c9d252 NC |
319 | } |
320 | break; | |
321 | ' | |
322 | ||
323 | # | |
324 | # Put these extra avr-elf routines in ld_${EMULATION_NAME}_emulation | |
325 | # | |
4d4ef6fd | 326 | LDEMUL_BEFORE_PARSE=avr_elf_before_parse |
28c9d252 | 327 | LDEMUL_BEFORE_ALLOCATION=avr_elf_${EMULATION_NAME}_before_allocation |
eaeb0a9d | 328 | LDEMUL_AFTER_ALLOCATION=avr_elf_after_allocation |
28c9d252 | 329 | LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=avr_elf_create_output_section_statements |
9d7b48dc | 330 | LDEMUL_FINISH=avr_finish |