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; | |
41 | ||
42 | return (link_info.output_bfd->xvec == &bfd_elf32_tic6x_le_vec | |
43 | || link_info.output_bfd->xvec == &bfd_elf32_tic6x_be_vec); | |
44 | } | |
45 | ||
46 | /* Pass params to backend. */ | |
47 | ||
48 | static void | |
49 | tic6x_after_open (void) | |
50 | { | |
51 | if (is_tic6x_target ()) | |
52 | { | |
53 | if (params.dsbt_index >= params.dsbt_size) | |
54 | { | |
55 | einfo (_("%P%F: invalid --dsbt-index %d, outside DSBT size.\n"), | |
56 | params.dsbt_index); | |
57 | } | |
58 | elf32_tic6x_setup (&link_info, ¶ms); | |
59 | } | |
60 | ||
61 | gld${EMULATION_NAME}_after_open (); | |
62 | } | |
fbd9ad90 PB |
63 | |
64 | static int | |
65 | compare_output_sec_vma (const void *a, const void *b) | |
66 | { | |
67 | asection *asec = *(asection **) a, *bsec = *(asection **) b; | |
68 | asection *aout = asec->output_section, *bout = bsec->output_section; | |
69 | bfd_vma avma, bvma; | |
70 | ||
71 | /* If there's no output section for some reason, compare equal. */ | |
72 | if (!aout || !bout) | |
73 | return 0; | |
74 | ||
75 | avma = aout->vma + asec->output_offset; | |
76 | bvma = bout->vma + bsec->output_offset; | |
77 | ||
78 | if (avma > bvma) | |
79 | return 1; | |
80 | else if (avma < bvma) | |
81 | return -1; | |
82 | ||
83 | return 0; | |
84 | } | |
85 | ||
86 | static void | |
87 | gld${EMULATION_NAME}_after_allocation (void) | |
88 | { | |
89 | int layout_changed = 0; | |
90 | ||
91 | if (!link_info.relocatable) | |
92 | { | |
93 | /* Build a sorted list of input text sections, then use that to process | |
94 | the unwind table index. */ | |
95 | unsigned int list_size = 10; | |
96 | asection **sec_list = (asection **) | |
97 | xmalloc (list_size * sizeof (asection *)); | |
98 | unsigned int sec_count = 0; | |
99 | ||
100 | LANG_FOR_EACH_INPUT_STATEMENT (is) | |
101 | { | |
102 | bfd *abfd = is->the_bfd; | |
103 | asection *sec; | |
104 | ||
105 | if ((abfd->flags & (EXEC_P | DYNAMIC)) != 0) | |
106 | continue; | |
107 | ||
108 | for (sec = abfd->sections; sec != NULL; sec = sec->next) | |
109 | { | |
110 | asection *out_sec = sec->output_section; | |
111 | ||
112 | if (out_sec | |
113 | && elf_section_data (sec) | |
114 | && elf_section_type (sec) == SHT_PROGBITS | |
115 | && (elf_section_flags (sec) & SHF_EXECINSTR) != 0 | |
116 | && (sec->flags & SEC_EXCLUDE) == 0 | |
117 | && sec->sec_info_type != ELF_INFO_TYPE_JUST_SYMS | |
118 | && out_sec != bfd_abs_section_ptr) | |
119 | { | |
120 | if (sec_count == list_size) | |
121 | { | |
122 | list_size *= 2; | |
123 | sec_list = (asection **) | |
124 | xrealloc (sec_list, list_size * sizeof (asection *)); | |
125 | } | |
126 | ||
127 | sec_list[sec_count++] = sec; | |
128 | } | |
129 | } | |
130 | } | |
131 | ||
132 | qsort (sec_list, sec_count, sizeof (asection *), &compare_output_sec_vma); | |
133 | ||
134 | if (elf32_tic6x_fix_exidx_coverage (sec_list, sec_count, &link_info, | |
135 | merge_exidx_entries)) | |
136 | layout_changed = 1; | |
137 | ||
138 | free (sec_list); | |
139 | } | |
140 | ||
141 | /* bfd_elf32_discard_info just plays with debugging sections, | |
142 | ie. doesn't affect any code, so we can delay resizing the | |
143 | sections. */ | |
144 | if (bfd_elf_discard_info (link_info.output_bfd, & link_info)) | |
145 | layout_changed = 1; | |
146 | ||
147 | gld${EMULATION_NAME}_map_segments (layout_changed); | |
148 | } | |
ac145307 BS |
149 | EOF |
150 | ||
151 | # This code gets inserted into the generic elf32.sc linker script | |
152 | # and allows us to define our own command line switches. | |
153 | PARSE_AND_LIST_PROLOGUE=' | |
154 | #define OPTION_DSBT_INDEX 300 | |
155 | #define OPTION_DSBT_SIZE 301 | |
fbd9ad90 | 156 | #define OPTION_NO_MERGE_EXIDX_ENTRIES 302 |
ac145307 BS |
157 | ' |
158 | ||
159 | PARSE_AND_LIST_LONGOPTS=' | |
160 | {"dsbt-index", required_argument, NULL, OPTION_DSBT_INDEX}, | |
161 | {"dsbt-size", required_argument, NULL, OPTION_DSBT_SIZE}, | |
fbd9ad90 | 162 | { "no-merge-exidx-entries", no_argument, NULL, OPTION_NO_MERGE_EXIDX_ENTRIES }, |
ac145307 BS |
163 | ' |
164 | ||
165 | PARSE_AND_LIST_OPTIONS=' | |
166 | fprintf (file, _(" --dsbt-index <index>\n")); | |
167 | fprintf (file, _("\t\t\tUse this as the DSBT index for the output object\n")); | |
168 | fprintf (file, _(" --dsbt-size <index>\n")); | |
169 | fprintf (file, _("\t\t\tUse this as the number of entries in the DSBT table\n")); | |
fbd9ad90 | 170 | fprintf (file, _(" --no-merge-exidx-entries Disable merging exidx entries\n")); |
ac145307 BS |
171 | ' |
172 | ||
173 | PARSE_AND_LIST_ARGS_CASES=' | |
174 | case OPTION_DSBT_INDEX: | |
175 | { | |
176 | char *end; | |
177 | params.dsbt_index = strtol (optarg, &end, 0); | |
178 | if (*end == 0 | |
179 | && params.dsbt_index >= 0 && params.dsbt_index < 0x7fff) | |
180 | break; | |
181 | einfo (_("%P%F: invalid --dsbt-index %s\n"), optarg); | |
182 | } | |
183 | break; | |
184 | case OPTION_DSBT_SIZE: | |
185 | { | |
186 | char *end; | |
187 | params.dsbt_size = strtol (optarg, &end, 0); | |
188 | if (*end == 0 | |
189 | && params.dsbt_size >= 0 && params.dsbt_size < 0x7fff) | |
190 | break; | |
191 | einfo (_("%P%F: invalid --dsbt-size %s\n"), optarg); | |
192 | } | |
193 | break; | |
fbd9ad90 PB |
194 | case OPTION_NO_MERGE_EXIDX_ENTRIES: |
195 | merge_exidx_entries = 0; | |
ac145307 BS |
196 | ' |
197 | ||
198 | LDEMUL_AFTER_OPEN=tic6x_after_open | |
fbd9ad90 | 199 | LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation |