Commit | Line | Data |
---|---|---|
ac145307 BS |
1 | # This shell script emits a C file. -*- C -*- |
2 | # Copyright 2011 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 | # | |
25 | fragment <<EOF | |
26 | #include "ldctor.h" | |
27 | #include "elf32-tic6x.h" | |
28 | ||
29 | static struct elf32_tic6x_params params = | |
30 | { | |
31 | 0, 64 | |
32 | }; | |
33 | ||
fbd9ad90 PB |
34 | static int merge_exidx_entries = -1; |
35 | ||
ac145307 BS |
36 | static int |
37 | is_tic6x_target (void) | |
38 | { | |
39 | extern const bfd_target bfd_elf32_tic6x_le_vec; | |
40 | extern const bfd_target bfd_elf32_tic6x_be_vec; | |
2a616379 BS |
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; | |
ac145307 BS |
45 | |
46 | return (link_info.output_bfd->xvec == &bfd_elf32_tic6x_le_vec | |
2a616379 BS |
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); | |
ac145307 BS |
52 | } |
53 | ||
54 | /* Pass params to backend. */ | |
55 | ||
56 | static void | |
57 | tic6x_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, ¶ms); | |
67 | } | |
68 | ||
69 | gld${EMULATION_NAME}_after_open (); | |
70 | } | |
fbd9ad90 PB |
71 | |
72 | static int | |
73 | compare_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 | ||
94 | static void | |
95 | gld${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 != ELF_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 | } | |
ac145307 BS |
157 | EOF |
158 | ||
159 | # This code gets inserted into the generic elf32.sc linker script | |
160 | # and allows us to define our own command line switches. | |
161 | PARSE_AND_LIST_PROLOGUE=' | |
162 | #define OPTION_DSBT_INDEX 300 | |
163 | #define OPTION_DSBT_SIZE 301 | |
fbd9ad90 | 164 | #define OPTION_NO_MERGE_EXIDX_ENTRIES 302 |
ac145307 BS |
165 | ' |
166 | ||
167 | PARSE_AND_LIST_LONGOPTS=' | |
168 | {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX}, | |
169 | {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE}, | |
fbd9ad90 | 170 | { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES }, |
ac145307 BS |
171 | ' |
172 | ||
173 | PARSE_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")); | |
fbd9ad90 | 178 | fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n")); |
ac145307 BS |
179 | ' |
180 | ||
181 | PARSE_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; | |
fbd9ad90 PB |
202 | case OPTION_NO_MERGE_EXIDX_ENTRIES: |
203 | merge_exidx_entries = 0; | |
ac145307 BS |
204 | ' |
205 | ||
206 | LDEMUL_AFTER_OPEN=tic6x_after_open | |
fbd9ad90 | 207 | LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation |