xref: /netbsd-src/external/gpl3/binutils/dist/ld/emultempl/tic6xdsbt.em (revision 6cd39ddb8550f6fa1bff3fed32053d7f19fd0453)
1# This shell script emits a C file. -*- C -*-
2#   Copyright 2011, 2012 Free Software Foundation, Inc.
3#
4# This file is part of the GNU Binutils.
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
8# the Free Software Foundation; either version 3 of the License, or
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
18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21
22# This file is sourced from elf32.em, and defines extra C6X DSBT specific
23# features.
24#
25fragment <<EOF
26#include "ldctor.h"
27#include "elf32-tic6x.h"
28
29static struct elf32_tic6x_params params =
30{
31  0, 64
32};
33
34static int merge_exidx_entries = -1;
35
36static int
37is_tic6x_target (void)
38{
39  extern const bfd_target bfd_elf32_tic6x_le_vec;
40  extern const bfd_target bfd_elf32_tic6x_be_vec;
41  extern const bfd_target bfd_elf32_tic6x_linux_le_vec;
42  extern const bfd_target bfd_elf32_tic6x_linux_be_vec;
43  extern const bfd_target bfd_elf32_tic6x_elf_le_vec;
44  extern const bfd_target bfd_elf32_tic6x_elf_be_vec;
45
46  return (link_info.output_bfd->xvec == &bfd_elf32_tic6x_le_vec
47  	  || link_info.output_bfd->xvec == &bfd_elf32_tic6x_be_vec
48	  || link_info.output_bfd->xvec == &bfd_elf32_tic6x_linux_le_vec
49  	  || link_info.output_bfd->xvec == &bfd_elf32_tic6x_linux_be_vec
50	  || link_info.output_bfd->xvec == &bfd_elf32_tic6x_elf_le_vec
51  	  || link_info.output_bfd->xvec == &bfd_elf32_tic6x_elf_be_vec);
52}
53
54/* Pass params to backend.  */
55
56static void
57tic6x_after_open (void)
58{
59  if (is_tic6x_target ())
60    {
61      if (params.dsbt_index >= params.dsbt_size)
62	{
63	  einfo (_("%P%F: invalid --dsbt-index %d, outside DSBT size.\n"),
64		 params.dsbt_index);
65	}
66      elf32_tic6x_setup (&link_info, &params);
67    }
68
69  gld${EMULATION_NAME}_after_open ();
70}
71
72static int
73compare_output_sec_vma (const void *a, const void *b)
74{
75  asection *asec = *(asection **) a, *bsec = *(asection **) b;
76  asection *aout = asec->output_section, *bout = bsec->output_section;
77  bfd_vma avma, bvma;
78
79  /* If there's no output section for some reason, compare equal.  */
80  if (!aout || !bout)
81    return 0;
82
83  avma = aout->vma + asec->output_offset;
84  bvma = bout->vma + bsec->output_offset;
85
86  if (avma > bvma)
87    return 1;
88  else if (avma < bvma)
89    return -1;
90
91  return 0;
92}
93
94static void
95gld${EMULATION_NAME}_after_allocation (void)
96{
97  int layout_changed = 0;
98
99  if (!link_info.relocatable)
100    {
101      /* Build a sorted list of input text sections, then use that to process
102	 the unwind table index.  */
103      unsigned int list_size = 10;
104      asection **sec_list = (asection **)
105          xmalloc (list_size * sizeof (asection *));
106      unsigned int sec_count = 0;
107
108      LANG_FOR_EACH_INPUT_STATEMENT (is)
109	{
110	  bfd *abfd = is->the_bfd;
111	  asection *sec;
112
113	  if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0)
114	    continue;
115
116	  for (sec = abfd->sections; sec != NULL; sec = sec->next)
117	    {
118	      asection *out_sec = sec->output_section;
119
120	      if (out_sec
121		  && elf_section_data (sec)
122		  && elf_section_type (sec) == SHT_PROGBITS
123		  && (elf_section_flags (sec) & SHF_EXECINSTR) != 0
124		  && (sec->flags & SEC_EXCLUDE) == 0
125		  && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS
126		  && out_sec != bfd_abs_section_ptr)
127		{
128		  if (sec_count == list_size)
129		    {
130		      list_size *= 2;
131		      sec_list = (asection **)
132                          xrealloc (sec_list, list_size * sizeof (asection *));
133		    }
134
135		  sec_list[sec_count++] = sec;
136		}
137	    }
138	}
139
140      qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma);
141
142      if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info,
143					   merge_exidx_entries))
144	layout_changed = 1;
145
146      free (sec_list);
147    }
148
149  /* bfd_elf32_discard_info just plays with debugging sections,
150     ie. doesn't affect any code, so we can delay resizing the
151     sections.  */
152  if (bfd_elf_discard_info (link_info.output_bfd, & link_info))
153    layout_changed = 1;
154
155  gld${EMULATION_NAME}_map_segments (layout_changed);
156}
157EOF
158
159# This code gets inserted into the generic elf32.sc linker script
160# and allows us to define our own command line switches.
161PARSE_AND_LIST_PROLOGUE='
162#define OPTION_DSBT_INDEX		300
163#define OPTION_DSBT_SIZE		301
164#define OPTION_NO_MERGE_EXIDX_ENTRIES   302
165'
166
167PARSE_AND_LIST_LONGOPTS='
168  {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX},
169  {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE},
170  { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES },
171'
172
173PARSE_AND_LIST_OPTIONS='
174  fprintf (file, _("  --dsbt-index <index>\n"));
175  fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n"));
176  fprintf (file, _("  --dsbt-size <index>\n"));
177  fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n"));
178  fprintf (file, _("  --no-merge-exidx-entries    Disable merging exidx entries\n"));
179'
180
181PARSE_AND_LIST_ARGS_CASES='
182    case OPTION_DSBT_INDEX:
183      {
184	char *end;
185	params.dsbt_index = strtol (optarg, &end, 0);
186	if (*end == 0
187	    && params.dsbt_index >= 0 && params.dsbt_index < 0x7fff)
188	  break;
189	einfo (_("%P%F: invalid --dsbt-index %s\n"), optarg);
190      }
191      break;
192    case OPTION_DSBT_SIZE:
193      {
194	char *end;
195	params.dsbt_size = strtol (optarg, &end, 0);
196	if (*end == 0
197	    && params.dsbt_size >= 0 && params.dsbt_size < 0x7fff)
198	  break;
199	einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg);
200      }
201      break;
202   case OPTION_NO_MERGE_EXIDX_ENTRIES:
203      merge_exidx_entries = 0;
204'
205
206LDEMUL_AFTER_OPEN=tic6x_after_open
207LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
208