1 |
38 |
julius |
# This shell script emits a C file. -*- C -*-
|
2 |
|
|
# Copyright 1991, 1993, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
|
3 |
|
|
# 2004, 2005, 2007, 2008
|
4 |
|
|
# Free Software Foundation, Inc.
|
5 |
|
|
#
|
6 |
|
|
# This file is part of the GNU Binutils.
|
7 |
|
|
#
|
8 |
|
|
# This program is free software; you can redistribute it and/or modify
|
9 |
|
|
# it under the terms of the GNU General Public License as published by
|
10 |
|
|
# the Free Software Foundation; either version 3 of the License, or
|
11 |
|
|
# (at your option) any later version.
|
12 |
|
|
#
|
13 |
|
|
# This program is distributed in the hope that it will be useful,
|
14 |
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15 |
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16 |
|
|
# GNU General Public License for more details.
|
17 |
|
|
#
|
18 |
|
|
# You should have received a copy of the GNU General Public License
|
19 |
|
|
# along with this program; if not, write to the Free Software
|
20 |
|
|
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
21 |
|
|
# MA 02110-1301, USA.
|
22 |
|
|
#
|
23 |
|
|
|
24 |
|
|
# This file is sourced from elf32.em, and defines extra arm-elf
|
25 |
|
|
# specific routines.
|
26 |
|
|
#
|
27 |
|
|
test -z "$TARGET2_TYPE" && TARGET2_TYPE="rel"
|
28 |
|
|
fragment <
|
29 |
|
|
|
30 |
|
|
#include "elf/arm.h"
|
31 |
|
|
|
32 |
|
|
static char *thumb_entry_symbol = NULL;
|
33 |
|
|
static bfd *bfd_for_interwork;
|
34 |
|
|
static int byteswap_code = 0;
|
35 |
|
|
static int target1_is_rel = 0${TARGET1_IS_REL};
|
36 |
|
|
static char *target2_type = "${TARGET2_TYPE}";
|
37 |
|
|
static int fix_v4bx = 0;
|
38 |
|
|
static int use_blx = 0;
|
39 |
|
|
static bfd_arm_vfp11_fix vfp11_denorm_fix = BFD_ARM_VFP11_FIX_DEFAULT;
|
40 |
|
|
static int no_enum_size_warning = 0;
|
41 |
|
|
static int pic_veneer = 0;
|
42 |
|
|
|
43 |
|
|
static void
|
44 |
|
|
gld${EMULATION_NAME}_before_parse (void)
|
45 |
|
|
{
|
46 |
|
|
#ifndef TARGET_ /* I.e., if not generic. */
|
47 |
|
|
ldfile_set_output_arch ("`echo ${ARCH}`", bfd_arch_unknown);
|
48 |
|
|
#endif /* not TARGET_ */
|
49 |
|
|
config.dynamic_link = ${DYNAMIC_LINK-TRUE};
|
50 |
|
|
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
|
51 |
|
|
}
|
52 |
|
|
|
53 |
|
|
static void
|
54 |
|
|
arm_elf_after_open (void)
|
55 |
|
|
{
|
56 |
|
|
if (strstr (bfd_get_target (link_info.output_bfd), "arm") == NULL)
|
57 |
|
|
{
|
58 |
|
|
/* The arm backend needs special fields in the output hash structure.
|
59 |
|
|
These will only be created if the output format is an arm format,
|
60 |
|
|
hence we do not support linking and changing output formats at the
|
61 |
|
|
same time. Use a link followed by objcopy to change output formats. */
|
62 |
|
|
einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n");
|
63 |
|
|
return;
|
64 |
|
|
}
|
65 |
|
|
|
66 |
|
|
{
|
67 |
|
|
LANG_FOR_EACH_INPUT_STATEMENT (is)
|
68 |
|
|
{
|
69 |
|
|
bfd_elf32_arm_add_glue_sections_to_bfd (is->the_bfd, & link_info);
|
70 |
|
|
}
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
/* Call the standard elf routine. */
|
74 |
|
|
gld${EMULATION_NAME}_after_open ();
|
75 |
|
|
}
|
76 |
|
|
|
77 |
|
|
static void
|
78 |
|
|
arm_elf_set_bfd_for_interworking (lang_statement_union_type *statement)
|
79 |
|
|
{
|
80 |
|
|
if (statement->header.type == lang_input_section_enum)
|
81 |
|
|
{
|
82 |
|
|
asection *i = statement->input_section.section;
|
83 |
|
|
|
84 |
|
|
if (!((lang_input_statement_type *) i->owner->usrdata)->just_syms_flag
|
85 |
|
|
&& (i->flags & SEC_EXCLUDE) == 0)
|
86 |
|
|
{
|
87 |
|
|
asection *output_section = i->output_section;
|
88 |
|
|
|
89 |
|
|
ASSERT (output_section->owner == link_info.output_bfd);
|
90 |
|
|
|
91 |
|
|
/* Don't attach the interworking stubs to a dynamic object, to
|
92 |
|
|
an empty section, etc. */
|
93 |
|
|
if ((output_section->flags & SEC_HAS_CONTENTS) != 0
|
94 |
|
|
&& (i->flags & SEC_NEVER_LOAD) == 0
|
95 |
|
|
&& ! (i->owner->flags & DYNAMIC)
|
96 |
|
|
&& ! i->owner->output_has_begun)
|
97 |
|
|
{
|
98 |
|
|
bfd_for_interwork = i->owner;
|
99 |
|
|
bfd_for_interwork->output_has_begun = TRUE;
|
100 |
|
|
}
|
101 |
|
|
}
|
102 |
|
|
}
|
103 |
|
|
}
|
104 |
|
|
|
105 |
|
|
static void
|
106 |
|
|
arm_elf_before_allocation (void)
|
107 |
|
|
{
|
108 |
|
|
bfd *tem;
|
109 |
|
|
|
110 |
|
|
if (link_info.input_bfds != NULL)
|
111 |
|
|
{
|
112 |
|
|
/* The interworking bfd must be the last one in the link. */
|
113 |
|
|
bfd_for_interwork = NULL;
|
114 |
|
|
for (tem = link_info.input_bfds; tem != NULL; tem = tem->link_next)
|
115 |
|
|
tem->output_has_begun = FALSE;
|
116 |
|
|
|
117 |
|
|
lang_for_each_statement (arm_elf_set_bfd_for_interworking);
|
118 |
|
|
for (tem = link_info.input_bfds; tem != NULL; tem = tem->link_next)
|
119 |
|
|
tem->output_has_begun = FALSE;
|
120 |
|
|
|
121 |
|
|
/* If bfd_for_interwork is NULL, then there are no loadable sections
|
122 |
|
|
with real contents to be linked, so we are not going to have to
|
123 |
|
|
create any interworking stubs, so it is OK not to call
|
124 |
|
|
bfd_elf32_arm_get_bfd_for_interworking. */
|
125 |
|
|
if (bfd_for_interwork != NULL)
|
126 |
|
|
bfd_elf32_arm_get_bfd_for_interworking (bfd_for_interwork, &link_info);
|
127 |
|
|
}
|
128 |
|
|
|
129 |
|
|
bfd_elf32_arm_set_byteswap_code (&link_info, byteswap_code);
|
130 |
|
|
|
131 |
|
|
/* Choose type of VFP11 erratum fix, or warn if specified fix is unnecessary
|
132 |
|
|
due to architecture version. */
|
133 |
|
|
bfd_elf32_arm_set_vfp11_fix (link_info.output_bfd, &link_info);
|
134 |
|
|
|
135 |
|
|
/* We should be able to set the size of the interworking stub section. We
|
136 |
|
|
can't do it until later if we have dynamic sections, though. */
|
137 |
|
|
if (! elf_hash_table (&link_info)->dynamic_sections_created)
|
138 |
|
|
{
|
139 |
|
|
/* Here we rummage through the found bfds to collect glue information. */
|
140 |
|
|
LANG_FOR_EACH_INPUT_STATEMENT (is)
|
141 |
|
|
{
|
142 |
|
|
/* Initialise mapping tables for code/data. */
|
143 |
|
|
bfd_elf32_arm_init_maps (is->the_bfd);
|
144 |
|
|
|
145 |
|
|
if (!bfd_elf32_arm_process_before_allocation (is->the_bfd,
|
146 |
|
|
&link_info)
|
147 |
|
|
|| !bfd_elf32_arm_vfp11_erratum_scan (is->the_bfd, &link_info))
|
148 |
|
|
/* xgettext:c-format */
|
149 |
|
|
einfo (_("Errors encountered processing file %s"), is->filename);
|
150 |
|
|
}
|
151 |
|
|
}
|
152 |
|
|
|
153 |
|
|
/* Call the standard elf routine. */
|
154 |
|
|
gld${EMULATION_NAME}_before_allocation ();
|
155 |
|
|
|
156 |
|
|
/* We have seen it all. Allocate it, and carry on. */
|
157 |
|
|
bfd_elf32_arm_allocate_interworking_sections (& link_info);
|
158 |
|
|
}
|
159 |
|
|
|
160 |
|
|
static void
|
161 |
|
|
arm_elf_after_allocation (void)
|
162 |
|
|
{
|
163 |
|
|
/* Call the standard elf routine. */
|
164 |
|
|
after_allocation_default ();
|
165 |
|
|
|
166 |
|
|
{
|
167 |
|
|
LANG_FOR_EACH_INPUT_STATEMENT (is)
|
168 |
|
|
{
|
169 |
|
|
/* Figure out where VFP11 erratum veneers (and the labels returning
|
170 |
|
|
from same) have been placed. */
|
171 |
|
|
bfd_elf32_arm_vfp11_fix_veneer_locations (is->the_bfd, &link_info);
|
172 |
|
|
}
|
173 |
|
|
}
|
174 |
|
|
}
|
175 |
|
|
|
176 |
|
|
static void
|
177 |
|
|
arm_elf_finish (void)
|
178 |
|
|
{
|
179 |
|
|
struct bfd_link_hash_entry * h;
|
180 |
|
|
|
181 |
|
|
/* Call the elf32.em routine. */
|
182 |
|
|
gld${EMULATION_NAME}_finish ();
|
183 |
|
|
|
184 |
|
|
if (thumb_entry_symbol)
|
185 |
|
|
{
|
186 |
|
|
h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol,
|
187 |
|
|
FALSE, FALSE, TRUE);
|
188 |
|
|
}
|
189 |
|
|
else
|
190 |
|
|
{
|
191 |
|
|
struct elf_link_hash_entry * eh;
|
192 |
|
|
|
193 |
|
|
if (!entry_symbol.name)
|
194 |
|
|
return;
|
195 |
|
|
|
196 |
|
|
h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
|
197 |
|
|
FALSE, FALSE, TRUE);
|
198 |
|
|
eh = (struct elf_link_hash_entry *)h;
|
199 |
|
|
if (!h || ELF_ST_TYPE(eh->type) != STT_ARM_TFUNC)
|
200 |
|
|
return;
|
201 |
|
|
}
|
202 |
|
|
|
203 |
|
|
|
204 |
|
|
if (h != (struct bfd_link_hash_entry *) NULL
|
205 |
|
|
&& (h->type == bfd_link_hash_defined
|
206 |
|
|
|| h->type == bfd_link_hash_defweak)
|
207 |
|
|
&& h->u.def.section->output_section != NULL)
|
208 |
|
|
{
|
209 |
|
|
static char buffer[32];
|
210 |
|
|
bfd_vma val;
|
211 |
|
|
|
212 |
|
|
/* Special procesing is required for a Thumb entry symbol. The
|
213 |
|
|
bottom bit of its address must be set. */
|
214 |
|
|
val = (h->u.def.value
|
215 |
|
|
+ bfd_get_section_vma (link_info.output_bfd,
|
216 |
|
|
h->u.def.section->output_section)
|
217 |
|
|
+ h->u.def.section->output_offset);
|
218 |
|
|
|
219 |
|
|
val |= 1;
|
220 |
|
|
|
221 |
|
|
/* Now convert this value into a string and store it in entry_symbol
|
222 |
|
|
where the lang_finish() function will pick it up. */
|
223 |
|
|
buffer[0] = '0';
|
224 |
|
|
buffer[1] = 'x';
|
225 |
|
|
|
226 |
|
|
sprintf_vma (buffer + 2, val);
|
227 |
|
|
|
228 |
|
|
if (thumb_entry_symbol != NULL && entry_symbol.name != NULL
|
229 |
|
|
&& entry_from_cmdline)
|
230 |
|
|
einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"),
|
231 |
|
|
thumb_entry_symbol, entry_symbol.name);
|
232 |
|
|
entry_symbol.name = buffer;
|
233 |
|
|
}
|
234 |
|
|
else
|
235 |
|
|
einfo (_("%P: warning: cannot find thumb start symbol %s\n"),
|
236 |
|
|
thumb_entry_symbol);
|
237 |
|
|
}
|
238 |
|
|
|
239 |
|
|
/* This is a convenient point to tell BFD about target specific flags.
|
240 |
|
|
After the output has been created, but before inputs are read. */
|
241 |
|
|
static void
|
242 |
|
|
arm_elf_create_output_section_statements (void)
|
243 |
|
|
{
|
244 |
|
|
bfd_elf32_arm_set_target_relocs (link_info.output_bfd, &link_info,
|
245 |
|
|
target1_is_rel,
|
246 |
|
|
target2_type, fix_v4bx, use_blx,
|
247 |
|
|
vfp11_denorm_fix, no_enum_size_warning,
|
248 |
|
|
pic_veneer);
|
249 |
|
|
}
|
250 |
|
|
|
251 |
|
|
EOF
|
252 |
|
|
|
253 |
|
|
# Define some shell vars to insert bits of code into the standard elf
|
254 |
|
|
# parse_args and list_options functions.
|
255 |
|
|
#
|
256 |
|
|
PARSE_AND_LIST_PROLOGUE='
|
257 |
|
|
#define OPTION_THUMB_ENTRY 301
|
258 |
|
|
#define OPTION_BE8 302
|
259 |
|
|
#define OPTION_TARGET1_REL 303
|
260 |
|
|
#define OPTION_TARGET1_ABS 304
|
261 |
|
|
#define OPTION_TARGET2 305
|
262 |
|
|
#define OPTION_FIX_V4BX 306
|
263 |
|
|
#define OPTION_USE_BLX 307
|
264 |
|
|
#define OPTION_VFP11_DENORM_FIX 308
|
265 |
|
|
#define OPTION_NO_ENUM_SIZE_WARNING 309
|
266 |
|
|
#define OPTION_PIC_VENEER 310
|
267 |
|
|
#define OPTION_FIX_V4BX_INTERWORKING 311
|
268 |
|
|
'
|
269 |
|
|
|
270 |
|
|
PARSE_AND_LIST_SHORTOPTS=p
|
271 |
|
|
|
272 |
|
|
PARSE_AND_LIST_LONGOPTS='
|
273 |
|
|
{ "no-pipeline-knowledge", no_argument, NULL, '\'p\''},
|
274 |
|
|
{ "thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY},
|
275 |
|
|
{ "be8", no_argument, NULL, OPTION_BE8},
|
276 |
|
|
{ "target1-rel", no_argument, NULL, OPTION_TARGET1_REL},
|
277 |
|
|
{ "target1-abs", no_argument, NULL, OPTION_TARGET1_ABS},
|
278 |
|
|
{ "target2", required_argument, NULL, OPTION_TARGET2},
|
279 |
|
|
{ "fix-v4bx", no_argument, NULL, OPTION_FIX_V4BX},
|
280 |
|
|
{ "fix-v4bx-interworking", no_argument, NULL, OPTION_FIX_V4BX_INTERWORKING},
|
281 |
|
|
{ "use-blx", no_argument, NULL, OPTION_USE_BLX},
|
282 |
|
|
{ "vfp11-denorm-fix", required_argument, NULL, OPTION_VFP11_DENORM_FIX},
|
283 |
|
|
{ "no-enum-size-warning", no_argument, NULL, OPTION_NO_ENUM_SIZE_WARNING},
|
284 |
|
|
{ "pic-veneer", no_argument, NULL, OPTION_PIC_VENEER},
|
285 |
|
|
'
|
286 |
|
|
|
287 |
|
|
PARSE_AND_LIST_OPTIONS='
|
288 |
|
|
fprintf (file, _(" --thumb-entry= Set the entry point to be Thumb symbol \n"));
|
289 |
|
|
fprintf (file, _(" --be8 Oputput BE8 format image\n"));
|
290 |
|
|
fprintf (file, _(" --target1=rel Interpret R_ARM_TARGET1 as R_ARM_REL32\n"));
|
291 |
|
|
fprintf (file, _(" --target1=abs Interpret R_ARM_TARGET1 as R_ARM_ABS32\n"));
|
292 |
|
|
fprintf (file, _(" --target2= Specify definition of R_ARM_TARGET2\n"));
|
293 |
|
|
fprintf (file, _(" --fix-v4bx Rewrite BX rn as MOV pc, rn for ARMv4\n"));
|
294 |
|
|
fprintf (file, _(" --fix-v4bx-interworking Rewrite BX rn branch to ARMv4 interworking veneer\n"));
|
295 |
|
|
fprintf (file, _(" --use-blx Enable use of BLX instructions\n"));
|
296 |
|
|
fprintf (file, _(" --vfp11-denorm-fix Specify how to fix VFP11 denorm erratum\n"));
|
297 |
|
|
fprintf (file, _(" --no-enum-size-warning Don'\''t warn about objects with incompatible"
|
298 |
|
|
" enum sizes\n"));
|
299 |
|
|
fprintf (file, _(" --pic-veneer Always generate PIC interworking veneers\n"));
|
300 |
|
|
'
|
301 |
|
|
|
302 |
|
|
PARSE_AND_LIST_ARGS_CASES='
|
303 |
|
|
case '\'p\'':
|
304 |
|
|
/* Only here for backwards compatibility. */
|
305 |
|
|
break;
|
306 |
|
|
|
307 |
|
|
case OPTION_THUMB_ENTRY:
|
308 |
|
|
thumb_entry_symbol = optarg;
|
309 |
|
|
break;
|
310 |
|
|
|
311 |
|
|
case OPTION_BE8:
|
312 |
|
|
byteswap_code = 1;
|
313 |
|
|
break;
|
314 |
|
|
|
315 |
|
|
case OPTION_TARGET1_REL:
|
316 |
|
|
target1_is_rel = 1;
|
317 |
|
|
break;
|
318 |
|
|
|
319 |
|
|
case OPTION_TARGET1_ABS:
|
320 |
|
|
target1_is_rel = 0;
|
321 |
|
|
break;
|
322 |
|
|
|
323 |
|
|
case OPTION_TARGET2:
|
324 |
|
|
target2_type = optarg;
|
325 |
|
|
break;
|
326 |
|
|
|
327 |
|
|
case OPTION_FIX_V4BX:
|
328 |
|
|
fix_v4bx = 1;
|
329 |
|
|
break;
|
330 |
|
|
|
331 |
|
|
case OPTION_FIX_V4BX_INTERWORKING:
|
332 |
|
|
fix_v4bx = 2;
|
333 |
|
|
break;
|
334 |
|
|
|
335 |
|
|
case OPTION_USE_BLX:
|
336 |
|
|
use_blx = 1;
|
337 |
|
|
break;
|
338 |
|
|
|
339 |
|
|
case OPTION_VFP11_DENORM_FIX:
|
340 |
|
|
if (strcmp (optarg, "none") == 0)
|
341 |
|
|
vfp11_denorm_fix = BFD_ARM_VFP11_FIX_NONE;
|
342 |
|
|
else if (strcmp (optarg, "scalar") == 0)
|
343 |
|
|
vfp11_denorm_fix = BFD_ARM_VFP11_FIX_SCALAR;
|
344 |
|
|
else if (strcmp (optarg, "vector") == 0)
|
345 |
|
|
vfp11_denorm_fix = BFD_ARM_VFP11_FIX_VECTOR;
|
346 |
|
|
else
|
347 |
|
|
einfo (_("Unrecognized VFP11 fix type '\''%s'\''.\n"), optarg);
|
348 |
|
|
break;
|
349 |
|
|
|
350 |
|
|
case OPTION_NO_ENUM_SIZE_WARNING:
|
351 |
|
|
no_enum_size_warning = 1;
|
352 |
|
|
break;
|
353 |
|
|
|
354 |
|
|
case OPTION_PIC_VENEER:
|
355 |
|
|
pic_veneer = 1;
|
356 |
|
|
break;
|
357 |
|
|
'
|
358 |
|
|
|
359 |
|
|
# We have our own after_open and before_allocation functions, but they call
|
360 |
|
|
# the standard routines, so give them a different name.
|
361 |
|
|
LDEMUL_AFTER_OPEN=arm_elf_after_open
|
362 |
|
|
LDEMUL_BEFORE_ALLOCATION=arm_elf_before_allocation
|
363 |
|
|
LDEMUL_AFTER_ALLOCATION=arm_elf_after_allocation
|
364 |
|
|
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=arm_elf_create_output_section_statements
|
365 |
|
|
|
366 |
|
|
# Replace the elf before_parse function with our own.
|
367 |
|
|
LDEMUL_BEFORE_PARSE=gld"${EMULATION_NAME}"_before_parse
|
368 |
|
|
|
369 |
|
|
# Call the extra arm-elf function
|
370 |
|
|
LDEMUL_FINISH=arm_elf_finish
|