mipself.em revision 1.10 1 1.1 christos # This shell script emits a C file. -*- C -*-
2 1.10 christos # Copyright (C) 2004-2025 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.7 christos case ${target} in
22 1.7 christos *-*-*gnu*)
23 1.8 christos gnu_target=true
24 1.7 christos ;;
25 1.7 christos *)
26 1.8 christos gnu_target=false
27 1.7 christos ;;
28 1.7 christos esac
29 1.7 christos
30 1.1 christos fragment <<EOF
31 1.1 christos
32 1.1 christos #include "ldctor.h"
33 1.1 christos #include "elf/mips.h"
34 1.1 christos #include "elfxx-mips.h"
35 1.1 christos
36 1.1 christos #define is_mips_elf(bfd) \
37 1.1 christos (bfd_get_flavour (bfd) == bfd_target_elf_flavour \
38 1.1 christos && elf_tdata (bfd) != NULL \
39 1.1 christos && elf_object_id (bfd) == MIPS_ELF_DATA)
40 1.1 christos
41 1.1 christos /* Fake input file for stubs. */
42 1.1 christos static lang_input_statement_type *stub_file;
43 1.1 christos static bfd *stub_bfd;
44 1.1 christos
45 1.8 christos static bool insn32;
46 1.8 christos static bool ignore_branch_isa;
47 1.8 christos static bool compact_branches;
48 1.1 christos
49 1.1 christos struct hook_stub_info
50 1.1 christos {
51 1.1 christos lang_statement_list_type add;
52 1.1 christos asection *input_section;
53 1.1 christos };
54 1.1 christos
55 1.1 christos /* Traverse the linker tree to find the spot where the stub goes. */
56 1.1 christos
57 1.8 christos static bool
58 1.1 christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
59 1.1 christos {
60 1.1 christos lang_statement_union_type *l;
61 1.8 christos bool ret;
62 1.1 christos
63 1.1 christos for (; (l = *lp) != NULL; lp = &l->header.next)
64 1.1 christos {
65 1.1 christos switch (l->header.type)
66 1.1 christos {
67 1.1 christos case lang_constructors_statement_enum:
68 1.1 christos ret = hook_in_stub (info, &constructor_list.head);
69 1.1 christos if (ret)
70 1.1 christos return ret;
71 1.1 christos break;
72 1.1 christos
73 1.1 christos case lang_output_section_statement_enum:
74 1.1 christos ret = hook_in_stub (info,
75 1.1 christos &l->output_section_statement.children.head);
76 1.1 christos if (ret)
77 1.1 christos return ret;
78 1.1 christos break;
79 1.1 christos
80 1.1 christos case lang_wild_statement_enum:
81 1.1 christos ret = hook_in_stub (info, &l->wild_statement.children.head);
82 1.1 christos if (ret)
83 1.1 christos return ret;
84 1.1 christos break;
85 1.1 christos
86 1.1 christos case lang_group_statement_enum:
87 1.1 christos ret = hook_in_stub (info, &l->group_statement.children.head);
88 1.1 christos if (ret)
89 1.1 christos return ret;
90 1.1 christos break;
91 1.1 christos
92 1.1 christos case lang_input_section_enum:
93 1.1 christos if (info->input_section == NULL
94 1.1 christos || l->input_section.section == info->input_section)
95 1.1 christos {
96 1.1 christos /* We've found our section. Insert the stub immediately
97 1.1 christos before its associated input section. */
98 1.1 christos *lp = info->add.head;
99 1.1 christos *(info->add.tail) = l;
100 1.8 christos return true;
101 1.1 christos }
102 1.1 christos break;
103 1.1 christos
104 1.1 christos case lang_data_statement_enum:
105 1.1 christos case lang_reloc_statement_enum:
106 1.1 christos case lang_object_symbols_statement_enum:
107 1.1 christos case lang_output_statement_enum:
108 1.1 christos case lang_target_statement_enum:
109 1.1 christos case lang_input_statement_enum:
110 1.1 christos case lang_assignment_statement_enum:
111 1.1 christos case lang_padding_statement_enum:
112 1.1 christos case lang_address_statement_enum:
113 1.1 christos case lang_fill_statement_enum:
114 1.1 christos break;
115 1.1 christos
116 1.1 christos default:
117 1.1 christos FAIL ();
118 1.1 christos break;
119 1.1 christos }
120 1.1 christos }
121 1.8 christos return false;
122 1.1 christos }
123 1.1 christos
124 1.1 christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
125 1.1 christos be linked in OUTPUT_SECTION. The section should go at the beginning of
126 1.1 christos OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
127 1.1 christos before INPUT_SECTION. */
128 1.1 christos
129 1.1 christos static asection *
130 1.1 christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
131 1.1 christos asection *output_section)
132 1.1 christos {
133 1.1 christos asection *stub_sec;
134 1.1 christos flagword flags;
135 1.1 christos lang_output_section_statement_type *os;
136 1.1 christos struct hook_stub_info info;
137 1.1 christos
138 1.1 christos /* PR 12845: If the input section has been garbage collected it will
139 1.1 christos not have its output section set to *ABS*. */
140 1.1 christos if (bfd_is_abs_section (output_section))
141 1.1 christos return NULL;
142 1.1 christos
143 1.1 christos /* Create the stub file, if we haven't already. */
144 1.1 christos if (stub_file == NULL)
145 1.1 christos {
146 1.1 christos stub_file = lang_add_input_file ("linker stubs",
147 1.1 christos lang_input_file_is_fake_enum,
148 1.1 christos NULL);
149 1.1 christos stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
150 1.1 christos if (stub_bfd == NULL
151 1.1 christos || !bfd_set_arch_mach (stub_bfd,
152 1.1 christos bfd_get_arch (link_info.output_bfd),
153 1.1 christos bfd_get_mach (link_info.output_bfd)))
154 1.1 christos {
155 1.10 christos fatal (_("%P: can not create BFD: %E\n"));
156 1.1 christos return NULL;
157 1.1 christos }
158 1.1 christos stub_bfd->flags |= BFD_LINKER_CREATED;
159 1.1 christos stub_file->the_bfd = stub_bfd;
160 1.1 christos ldlang_add_file (stub_file);
161 1.1 christos }
162 1.1 christos
163 1.1 christos /* Create the section. */
164 1.1 christos stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
165 1.1 christos if (stub_sec == NULL)
166 1.1 christos goto err_ret;
167 1.1 christos
168 1.1 christos /* Set the flags. */
169 1.1 christos flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
170 1.1 christos | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
171 1.7 christos if (!bfd_set_section_flags (stub_sec, flags))
172 1.1 christos goto err_ret;
173 1.1 christos
174 1.3 christos os = lang_output_section_get (output_section);
175 1.1 christos
176 1.1 christos /* Initialize a statement list that contains only the new statement. */
177 1.1 christos lang_list_init (&info.add);
178 1.8 christos lang_add_section (&info.add, stub_sec, NULL, NULL, os);
179 1.1 christos if (info.add.head == NULL)
180 1.1 christos goto err_ret;
181 1.1 christos
182 1.1 christos /* Insert the new statement in the appropriate place. */
183 1.1 christos info.input_section = input_section;
184 1.1 christos if (hook_in_stub (&info, &os->children.head))
185 1.1 christos return stub_sec;
186 1.1 christos
187 1.1 christos err_ret:
188 1.6 christos einfo (_("%X%P: can not make stub section: %E\n"));
189 1.1 christos return NULL;
190 1.1 christos }
191 1.1 christos
192 1.1 christos /* This is called before the input files are opened. */
193 1.1 christos
194 1.1 christos static void
195 1.1 christos mips_create_output_section_statements (void)
196 1.1 christos {
197 1.3 christos struct elf_link_hash_table *htab;
198 1.3 christos
199 1.3 christos htab = elf_hash_table (&link_info);
200 1.8 christos if (is_elf_hash_table (&htab->root) && is_mips_elf (link_info.output_bfd))
201 1.7 christos _bfd_mips_elf_linker_flags (&link_info, insn32, ignore_branch_isa,
202 1.7 christos ${gnu_target});
203 1.3 christos
204 1.1 christos if (is_mips_elf (link_info.output_bfd))
205 1.7 christos {
206 1.7 christos _bfd_mips_elf_compact_branches (&link_info, compact_branches);
207 1.7 christos _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
208 1.7 christos }
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.6 christos if (is_mips_elf (link_info.output_bfd))
217 1.6 christos {
218 1.6 christos flagword flags;
219 1.1 christos
220 1.6 christos flags = elf_elfheader (link_info.output_bfd)->e_flags;
221 1.6 christos if (!bfd_link_pic (&link_info)
222 1.6 christos && !link_info.nocopyreloc
223 1.6 christos && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
224 1.6 christos _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
225 1.6 christos }
226 1.1 christos
227 1.1 christos gld${EMULATION_NAME}_before_allocation ();
228 1.1 christos }
229 1.1 christos
230 1.1 christos EOF
231 1.1 christos
232 1.3 christos # Define some shell vars to insert bits of code into the standard elf
233 1.3 christos # parse_args and list_options functions.
234 1.3 christos #
235 1.3 christos PARSE_AND_LIST_LONGOPTS='
236 1.3 christos { "insn32", no_argument, NULL, OPTION_INSN32 },
237 1.3 christos { "no-insn32", no_argument, NULL, OPTION_NO_INSN32 },
238 1.6 christos { "ignore-branch-isa", no_argument, NULL, OPTION_IGNORE_BRANCH_ISA },
239 1.6 christos { "no-ignore-branch-isa", no_argument, NULL, OPTION_NO_IGNORE_BRANCH_ISA },
240 1.7 christos { "compact-branches", no_argument, NULL, OPTION_COMPACT_BRANCHES },
241 1.7 christos { "no-compact-branches", no_argument, NULL, OPTION_NO_COMPACT_BRANCHES },
242 1.3 christos '
243 1.3 christos
244 1.3 christos PARSE_AND_LIST_OPTIONS='
245 1.3 christos fprintf (file, _("\
246 1.3 christos --insn32 Only generate 32-bit microMIPS instructions\n"
247 1.3 christos ));
248 1.3 christos fprintf (file, _("\
249 1.3 christos --no-insn32 Generate all microMIPS instructions\n"
250 1.3 christos ));
251 1.6 christos fprintf (file, _("\
252 1.6 christos --ignore-branch-isa Accept invalid branch relocations requiring\n\
253 1.6 christos an ISA mode switch\n"
254 1.6 christos ));
255 1.6 christos fprintf (file, _("\
256 1.6 christos --no-ignore-branch-isa Reject invalid branch relocations requiring\n\
257 1.6 christos an ISA mode switch\n"
258 1.6 christos ));
259 1.7 christos fprintf (file, _("\
260 1.7 christos --compact-branches Generate compact branches/jumps for MIPS R6\n"
261 1.7 christos ));
262 1.7 christos fprintf (file, _("\
263 1.7 christos --no-compact-branches Generate delay slot branches/jumps for MIPS R6\n"
264 1.7 christos ));
265 1.3 christos '
266 1.3 christos
267 1.3 christos PARSE_AND_LIST_ARGS_CASES='
268 1.3 christos case OPTION_INSN32:
269 1.8 christos insn32 = true;
270 1.3 christos break;
271 1.3 christos
272 1.3 christos case OPTION_NO_INSN32:
273 1.8 christos insn32 = false;
274 1.3 christos break;
275 1.6 christos
276 1.6 christos case OPTION_IGNORE_BRANCH_ISA:
277 1.8 christos ignore_branch_isa = true;
278 1.6 christos break;
279 1.6 christos
280 1.6 christos case OPTION_NO_IGNORE_BRANCH_ISA:
281 1.8 christos ignore_branch_isa = false;
282 1.6 christos break;
283 1.7 christos
284 1.7 christos case OPTION_COMPACT_BRANCHES:
285 1.8 christos compact_branches = true;
286 1.7 christos break;
287 1.7 christos
288 1.7 christos case OPTION_NO_COMPACT_BRANCHES:
289 1.8 christos compact_branches = false;
290 1.7 christos break;
291 1.3 christos '
292 1.3 christos
293 1.1 christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
294 1.1 christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
295