Commit | Line | Data |
---|---|---|
ac145307 | 1 | # This shell script emits a C file. -*- C -*- |
6f2750fe | 2 | # Copyright (C) 2011-2016 Free Software Foundation, Inc. |
ac145307 BS |
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 | { | |
6d00b590 AM |
39 | extern const bfd_target tic6x_elf32_le_vec; |
40 | extern const bfd_target tic6x_elf32_be_vec; | |
41 | extern const bfd_target tic6x_elf32_linux_le_vec; | |
42 | extern const bfd_target tic6x_elf32_linux_be_vec; | |
43 | extern const bfd_target tic6x_elf32_c6000_le_vec; | |
44 | extern const bfd_target tic6x_elf32_c6000_be_vec; | |
ac145307 | 45 | |
6d00b590 AM |
46 | return (link_info.output_bfd->xvec == &tic6x_elf32_le_vec |
47 | || link_info.output_bfd->xvec == &tic6x_elf32_be_vec | |
48 | || link_info.output_bfd->xvec == &tic6x_elf32_linux_le_vec | |
49 | || link_info.output_bfd->xvec == &tic6x_elf32_linux_be_vec | |
50 | || link_info.output_bfd->xvec == &tic6x_elf32_c6000_le_vec | |
51 | || link_info.output_bfd->xvec == &tic6x_elf32_c6000_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; | |
e4492aa0 | 78 | |
fbd9ad90 PB |
79 | /* If there's no output section for some reason, compare equal. */ |
80 | if (!aout || !bout) | |
81 | return 0; | |
e4492aa0 | 82 | |
fbd9ad90 PB |
83 | avma = aout->vma + asec->output_offset; |
84 | bvma = bout->vma + bsec->output_offset; | |
e4492aa0 | 85 | |
fbd9ad90 PB |
86 | if (avma > bvma) |
87 | return 1; | |
88 | else if (avma < bvma) | |
89 | return -1; | |
e4492aa0 | 90 | |
fbd9ad90 PB |
91 | return 0; |
92 | } | |
93 | ||
94 | static void | |
95 | gld${EMULATION_NAME}_after_allocation (void) | |
96 | { | |
97 | int layout_changed = 0; | |
75938853 | 98 | int ret; |
fbd9ad90 | 99 | |
0e1862bb | 100 | if (!bfd_link_relocatable (&link_info)) |
fbd9ad90 PB |
101 | { |
102 | /* Build a sorted list of input text sections, then use that to process | |
103 | the unwind table index. */ | |
104 | unsigned int list_size = 10; | |
105 | asection **sec_list = (asection **) | |
106 | xmalloc (list_size * sizeof (asection *)); | |
107 | unsigned int sec_count = 0; | |
108 | ||
109 | LANG_FOR_EACH_INPUT_STATEMENT (is) | |
110 | { | |
111 | bfd *abfd = is->the_bfd; | |
112 | asection *sec; | |
e4492aa0 | 113 | |
fbd9ad90 PB |
114 | if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) |
115 | continue; | |
e4492aa0 | 116 | |
fbd9ad90 PB |
117 | for (sec = abfd->sections; sec != NULL; sec = sec->next) |
118 | { | |
119 | asection *out_sec = sec->output_section; | |
120 | ||
121 | if (out_sec | |
122 | && elf_section_data (sec) | |
123 | && elf_section_type (sec) == SHT_PROGBITS | |
124 | && (elf_section_flags (sec) & SHF_EXECINSTR) != 0 | |
125 | && (sec->flags & SEC_EXCLUDE) == 0 | |
dbaa2011 | 126 | && sec->sec_info_type != SEC_INFO_TYPE_JUST_SYMS |
fbd9ad90 PB |
127 | && out_sec != bfd_abs_section_ptr) |
128 | { | |
129 | if (sec_count == list_size) | |
130 | { | |
131 | list_size *= 2; | |
e4492aa0 | 132 | sec_list = (asection **) |
fbd9ad90 PB |
133 | xrealloc (sec_list, list_size * sizeof (asection *)); |
134 | } | |
135 | ||
136 | sec_list[sec_count++] = sec; | |
137 | } | |
138 | } | |
139 | } | |
e4492aa0 | 140 | |
fbd9ad90 | 141 | qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma); |
e4492aa0 | 142 | |
fbd9ad90 PB |
143 | if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info, |
144 | merge_exidx_entries)) | |
145 | layout_changed = 1; | |
e4492aa0 | 146 | |
fbd9ad90 PB |
147 | free (sec_list); |
148 | } | |
149 | ||
150 | /* bfd_elf32_discard_info just plays with debugging sections, | |
151 | ie. doesn't affect any code, so we can delay resizing the | |
152 | sections. */ | |
75938853 AM |
153 | ret = bfd_elf_discard_info (link_info.output_bfd, & link_info); |
154 | if (ret < 0) | |
155 | { | |
156 | einfo ("%X%P: .eh_frame/.stab edit: %E\n"); | |
157 | return; | |
158 | } | |
159 | else if (ret > 0) | |
fbd9ad90 PB |
160 | layout_changed = 1; |
161 | ||
162 | gld${EMULATION_NAME}_map_segments (layout_changed); | |
163 | } | |
ac145307 BS |
164 | EOF |
165 | ||
166 | # This code gets inserted into the generic elf32.sc linker script | |
167 | # and allows us to define our own command line switches. | |
168 | PARSE_AND_LIST_PROLOGUE=' | |
169 | #define OPTION_DSBT_INDEX 300 | |
170 | #define OPTION_DSBT_SIZE 301 | |
fbd9ad90 | 171 | #define OPTION_NO_MERGE_EXIDX_ENTRIES 302 |
ac145307 BS |
172 | ' |
173 | ||
174 | PARSE_AND_LIST_LONGOPTS=' | |
175 | {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX}, | |
176 | {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE}, | |
fbd9ad90 | 177 | { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES }, |
ac145307 BS |
178 | ' |
179 | ||
180 | PARSE_AND_LIST_OPTIONS=' | |
181 | fprintf (file, _(" --dsbt-index <index>\n")); | |
182 | fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n")); | |
183 | fprintf (file, _(" --dsbt-size <index>\n")); | |
184 | fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n")); | |
fbd9ad90 | 185 | fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n")); |
ac145307 BS |
186 | ' |
187 | ||
188 | PARSE_AND_LIST_ARGS_CASES=' | |
189 | case OPTION_DSBT_INDEX: | |
190 | { | |
191 | char *end; | |
192 | params.dsbt_index = strtol (optarg, &end, 0); | |
193 | if (*end == 0 | |
194 | && params.dsbt_index >= 0 && params.dsbt_index < 0x7fff) | |
195 | break; | |
196 | einfo (_("%P%F: invalid --dsbt-index %s\n"), optarg); | |
197 | } | |
198 | break; | |
199 | case OPTION_DSBT_SIZE: | |
200 | { | |
201 | char *end; | |
202 | params.dsbt_size = strtol (optarg, &end, 0); | |
203 | if (*end == 0 | |
204 | && params.dsbt_size >= 0 && params.dsbt_size < 0x7fff) | |
205 | break; | |
206 | einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg); | |
207 | } | |
208 | break; | |
fbd9ad90 PB |
209 | case OPTION_NO_MERGE_EXIDX_ENTRIES: |
210 | merge_exidx_entries = 0; | |
ac145307 BS |
211 | ' |
212 | ||
213 | LDEMUL_AFTER_OPEN=tic6x_after_open | |
fbd9ad90 | 214 | LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation |