mipself.em revision 1.3 1 1.1 christos # This shell script emits a C file. -*- C -*-
2 1.3 christos # Copyright (C) 2004-2015 Free Software Foundation, Inc.
3 1.1 christos #
4 1.1 christos # This file is part of the GNU Binutils.
5 1.1 christos #
6 1.1 christos # This program is free software; you can redistribute it and/or modify
7 1.1 christos # it under the terms of the GNU General Public License as published by
8 1.1 christos # the Free Software Foundation; either version 3 of the License, or
9 1.1 christos # (at your option) any later version.
10 1.1 christos #
11 1.1 christos # This program is distributed in the hope that it will be useful,
12 1.1 christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos # GNU General Public License for more details.
15 1.1 christos #
16 1.1 christos # You should have received a copy of the GNU General Public License
17 1.1 christos # along with this program; if not, write to the Free Software
18 1.1 christos # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos # MA 02110-1301, USA.
20 1.1 christos
21 1.1 christos fragment <<EOF
22 1.1 christos
23 1.1 christos #include "ldctor.h"
24 1.1 christos #include "elf/mips.h"
25 1.1 christos #include "elfxx-mips.h"
26 1.1 christos
27 1.1 christos #define is_mips_elf(bfd) \
28 1.1 christos (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
29 1.1 christos && elf_tdata (bfd) != NULL \
30 1.1 christos && elf_object_id (bfd) == MIPS_ELF_DATA)
31 1.1 christos
32 1.1 christos /* Fake input file for stubs. */
33 1.1 christos static lang_input_statement_type *stub_file;
34 1.1 christos static bfd *stub_bfd;
35 1.1 christos
36 1.3 christos static bfd_boolean insn32;
37 1.3 christos
38 1.1 christos static void
39 1.1 christos mips_after_parse (void)
40 1.1 christos {
41 1.1 christos /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
42 1.1 christos ways. .gnu.hash needs symbols to be grouped by hash code whereas the
43 1.1 christos MIPS ABI requires a mapping between the GOT and the symbol table. */
44 1.1 christos if (link_info.emit_gnu_hash)
45 1.1 christos {
46 1.1 christos einfo ("%X%P: .gnu.hash is incompatible with the MIPS ABI\n");
47 1.1 christos link_info.emit_hash = TRUE;
48 1.1 christos link_info.emit_gnu_hash = FALSE;
49 1.1 christos }
50 1.3 christos gld${EMULATION_NAME}_after_parse ();
51 1.1 christos }
52 1.1 christos
53 1.1 christos struct hook_stub_info
54 1.1 christos {
55 1.1 christos lang_statement_list_type add;
56 1.1 christos asection *input_section;
57 1.1 christos };
58 1.1 christos
59 1.1 christos /* Traverse the linker tree to find the spot where the stub goes. */
60 1.1 christos
61 1.1 christos static bfd_boolean
62 1.1 christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
63 1.1 christos {
64 1.1 christos lang_statement_union_type *l;
65 1.1 christos bfd_boolean ret;
66 1.1 christos
67 1.1 christos for (; (l = *lp) != NULL; lp = &l->header.next)
68 1.1 christos {
69 1.1 christos switch (l->header.type)
70 1.1 christos {
71 1.1 christos case lang_constructors_statement_enum:
72 1.1 christos ret = hook_in_stub (info, &constructor_list.head);
73 1.1 christos if (ret)
74 1.1 christos return ret;
75 1.1 christos break;
76 1.1 christos
77 1.1 christos case lang_output_section_statement_enum:
78 1.1 christos ret = hook_in_stub (info,
79 1.1 christos &l->output_section_statement.children.head);
80 1.1 christos if (ret)
81 1.1 christos return ret;
82 1.1 christos break;
83 1.1 christos
84 1.1 christos case lang_wild_statement_enum:
85 1.1 christos ret = hook_in_stub (info, &l->wild_statement.children.head);
86 1.1 christos if (ret)
87 1.1 christos return ret;
88 1.1 christos break;
89 1.1 christos
90 1.1 christos case lang_group_statement_enum:
91 1.1 christos ret = hook_in_stub (info, &l->group_statement.children.head);
92 1.1 christos if (ret)
93 1.1 christos return ret;
94 1.1 christos break;
95 1.1 christos
96 1.1 christos case lang_input_section_enum:
97 1.1 christos if (info->input_section == NULL
98 1.1 christos || l->input_section.section == info->input_section)
99 1.1 christos {
100 1.1 christos /* We've found our section. Insert the stub immediately
101 1.1 christos before its associated input section. */
102 1.1 christos *lp = info->add.head;
103 1.1 christos *(info->add.tail) = l;
104 1.1 christos return TRUE;
105 1.1 christos }
106 1.1 christos break;
107 1.1 christos
108 1.1 christos case lang_data_statement_enum:
109 1.1 christos case lang_reloc_statement_enum:
110 1.1 christos case lang_object_symbols_statement_enum:
111 1.1 christos case lang_output_statement_enum:
112 1.1 christos case lang_target_statement_enum:
113 1.1 christos case lang_input_statement_enum:
114 1.1 christos case lang_assignment_statement_enum:
115 1.1 christos case lang_padding_statement_enum:
116 1.1 christos case lang_address_statement_enum:
117 1.1 christos case lang_fill_statement_enum:
118 1.1 christos break;
119 1.1 christos
120 1.1 christos default:
121 1.1 christos FAIL ();
122 1.1 christos break;
123 1.1 christos }
124 1.1 christos }
125 1.1 christos return FALSE;
126 1.1 christos }
127 1.1 christos
128 1.1 christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
129 1.1 christos be linked in OUTPUT_SECTION. The section should go at the beginning of
130 1.1 christos OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
131 1.1 christos before INPUT_SECTION. */
132 1.1 christos
133 1.1 christos static asection *
134 1.1 christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
135 1.1 christos asection *output_section)
136 1.1 christos {
137 1.1 christos asection *stub_sec;
138 1.1 christos flagword flags;
139 1.1 christos lang_output_section_statement_type *os;
140 1.1 christos struct hook_stub_info info;
141 1.1 christos
142 1.1 christos /* PR 12845: If the input section has been garbage collected it will
143 1.1 christos not have its output section set to *ABS*. */
144 1.1 christos if (bfd_is_abs_section (output_section))
145 1.1 christos return NULL;
146 1.1 christos
147 1.1 christos /* Create the stub file, if we haven't already. */
148 1.1 christos if (stub_file == NULL)
149 1.1 christos {
150 1.1 christos stub_file = lang_add_input_file ("linker stubs",
151 1.1 christos lang_input_file_is_fake_enum,
152 1.1 christos NULL);
153 1.1 christos stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
154 1.1 christos if (stub_bfd == NULL
155 1.1 christos || !bfd_set_arch_mach (stub_bfd,
156 1.1 christos bfd_get_arch (link_info.output_bfd),
157 1.1 christos bfd_get_mach (link_info.output_bfd)))
158 1.1 christos {
159 1.1 christos einfo ("%F%P: can not create BFD %E\n");
160 1.1 christos return NULL;
161 1.1 christos }
162 1.1 christos stub_bfd->flags |= BFD_LINKER_CREATED;
163 1.1 christos stub_file->the_bfd = stub_bfd;
164 1.1 christos ldlang_add_file (stub_file);
165 1.1 christos }
166 1.1 christos
167 1.1 christos /* Create the section. */
168 1.1 christos stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
169 1.1 christos if (stub_sec == NULL)
170 1.1 christos goto err_ret;
171 1.1 christos
172 1.1 christos /* Set the flags. */
173 1.1 christos flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
174 1.1 christos | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
175 1.1 christos if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
176 1.1 christos goto err_ret;
177 1.1 christos
178 1.3 christos os = lang_output_section_get (output_section);
179 1.1 christos
180 1.1 christos /* Initialize a statement list that contains only the new statement. */
181 1.1 christos lang_list_init (&info.add);
182 1.1 christos lang_add_section (&info.add, stub_sec, NULL, os);
183 1.1 christos if (info.add.head == NULL)
184 1.1 christos goto err_ret;
185 1.1 christos
186 1.1 christos /* Insert the new statement in the appropriate place. */
187 1.1 christos info.input_section = input_section;
188 1.1 christos if (hook_in_stub (&info, &os->children.head))
189 1.1 christos return stub_sec;
190 1.1 christos
191 1.1 christos err_ret:
192 1.1 christos einfo ("%X%P: can not make stub section: %E\n");
193 1.1 christos return NULL;
194 1.1 christos }
195 1.1 christos
196 1.1 christos /* This is called before the input files are opened. */
197 1.1 christos
198 1.1 christos static void
199 1.1 christos mips_create_output_section_statements (void)
200 1.1 christos {
201 1.3 christos struct elf_link_hash_table *htab;
202 1.3 christos
203 1.3 christos htab = elf_hash_table (&link_info);
204 1.3 christos if (is_elf_hash_table (htab) && is_mips_elf (link_info.output_bfd))
205 1.3 christos _bfd_mips_elf_insn32 (&link_info, insn32);
206 1.3 christos
207 1.1 christos if (is_mips_elf (link_info.output_bfd))
208 1.1 christos _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
209 1.1 christos }
210 1.1 christos
211 1.1 christos /* This is called after we have merged the private data of the input bfds. */
212 1.1 christos
213 1.1 christos static void
214 1.1 christos mips_before_allocation (void)
215 1.1 christos {
216 1.1 christos flagword flags;
217 1.1 christos
218 1.1 christos flags = elf_elfheader (link_info.output_bfd)->e_flags;
219 1.3 christos if (!bfd_link_pic (&link_info)
220 1.1 christos && !link_info.nocopyreloc
221 1.1 christos && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
222 1.1 christos _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
223 1.1 christos
224 1.1 christos gld${EMULATION_NAME}_before_allocation ();
225 1.1 christos }
226 1.1 christos
227 1.1 christos /* Avoid processing the fake stub_file in vercheck, stat_needed and
228 1.1 christos check_needed routines. */
229 1.1 christos
230 1.1 christos static void (*real_func) (lang_input_statement_type *);
231 1.1 christos
232 1.1 christos static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
233 1.1 christos {
234 1.1 christos if (l != stub_file)
235 1.1 christos (*real_func) (l);
236 1.1 christos }
237 1.1 christos
238 1.1 christos static void
239 1.1 christos mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
240 1.1 christos {
241 1.1 christos real_func = func;
242 1.1 christos lang_for_each_input_file (&mips_for_each_input_file_wrapper);
243 1.1 christos }
244 1.1 christos
245 1.1 christos #define lang_for_each_input_file mips_lang_for_each_input_file
246 1.1 christos
247 1.1 christos EOF
248 1.1 christos
249 1.3 christos # Define some shell vars to insert bits of code into the standard elf
250 1.3 christos # parse_args and list_options functions.
251 1.3 christos #
252 1.3 christos PARSE_AND_LIST_PROLOGUE='
253 1.3 christos #define OPTION_INSN32 301
254 1.3 christos #define OPTION_NO_INSN32 (OPTION_INSN32 + 1)
255 1.3 christos '
256 1.3 christos
257 1.3 christos PARSE_AND_LIST_LONGOPTS='
258 1.3 christos { "insn32", no_argument, NULL, OPTION_INSN32 },
259 1.3 christos { "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
260 1.3 christos '
261 1.3 christos
262 1.3 christos PARSE_AND_LIST_OPTIONS='
263 1.3 christos fprintf (file, _("\
264 1.3 christos --insn32 Only generate 32-bit microMIPS instructions\n"
265 1.3 christos ));
266 1.3 christos fprintf (file, _("\
267 1.3 christos --no-insn32 Generate all microMIPS instructions\n"
268 1.3 christos ));
269 1.3 christos '
270 1.3 christos
271 1.3 christos PARSE_AND_LIST_ARGS_CASES='
272 1.3 christos case OPTION_INSN32:
273 1.3 christos insn32 = TRUE;
274 1.3 christos break;
275 1.3 christos
276 1.3 christos case OPTION_NO_INSN32:
277 1.3 christos insn32 = FALSE;
278 1.3 christos break;
279 1.3 christos '
280 1.3 christos
281 1.1 christos LDEMUL_AFTER_PARSE=mips_after_parse
282 1.1 christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
283 1.1 christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
284