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