mipself.em revision 1.1 1 1.1 christos # This shell script emits a C file. -*- C -*-
2 1.1 christos # Copyright 2004, 2006, 2007, 2008 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.1 christos static void
37 1.1 christos mips_after_parse (void)
38 1.1 christos {
39 1.1 christos /* .gnu.hash and the MIPS ABI require .dynsym to be sorted in different
40 1.1 christos ways. .gnu.hash needs symbols to be grouped by hash code whereas the
41 1.1 christos MIPS ABI requires a mapping between the GOT and the symbol table. */
42 1.1 christos if (link_info.emit_gnu_hash)
43 1.1 christos {
44 1.1 christos einfo ("%X%P: .gnu.hash is incompatible with the MIPS ABI\n");
45 1.1 christos link_info.emit_hash = TRUE;
46 1.1 christos link_info.emit_gnu_hash = FALSE;
47 1.1 christos }
48 1.1 christos after_parse_default ();
49 1.1 christos }
50 1.1 christos
51 1.1 christos struct hook_stub_info
52 1.1 christos {
53 1.1 christos lang_statement_list_type add;
54 1.1 christos asection *input_section;
55 1.1 christos };
56 1.1 christos
57 1.1 christos /* Traverse the linker tree to find the spot where the stub goes. */
58 1.1 christos
59 1.1 christos static bfd_boolean
60 1.1 christos hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
61 1.1 christos {
62 1.1 christos lang_statement_union_type *l;
63 1.1 christos bfd_boolean ret;
64 1.1 christos
65 1.1 christos for (; (l = *lp) != NULL; lp = &l->header.next)
66 1.1 christos {
67 1.1 christos switch (l->header.type)
68 1.1 christos {
69 1.1 christos case lang_constructors_statement_enum:
70 1.1 christos ret = hook_in_stub (info, &constructor_list.head);
71 1.1 christos if (ret)
72 1.1 christos return ret;
73 1.1 christos break;
74 1.1 christos
75 1.1 christos case lang_output_section_statement_enum:
76 1.1 christos ret = hook_in_stub (info,
77 1.1 christos &l->output_section_statement.children.head);
78 1.1 christos if (ret)
79 1.1 christos return ret;
80 1.1 christos break;
81 1.1 christos
82 1.1 christos case lang_wild_statement_enum:
83 1.1 christos ret = hook_in_stub (info, &l->wild_statement.children.head);
84 1.1 christos if (ret)
85 1.1 christos return ret;
86 1.1 christos break;
87 1.1 christos
88 1.1 christos case lang_group_statement_enum:
89 1.1 christos ret = hook_in_stub (info, &l->group_statement.children.head);
90 1.1 christos if (ret)
91 1.1 christos return ret;
92 1.1 christos break;
93 1.1 christos
94 1.1 christos case lang_input_section_enum:
95 1.1 christos if (info->input_section == NULL
96 1.1 christos || l->input_section.section == info->input_section)
97 1.1 christos {
98 1.1 christos /* We've found our section. Insert the stub immediately
99 1.1 christos before its associated input section. */
100 1.1 christos *lp = info->add.head;
101 1.1 christos *(info->add.tail) = l;
102 1.1 christos return TRUE;
103 1.1 christos }
104 1.1 christos break;
105 1.1 christos
106 1.1 christos case lang_data_statement_enum:
107 1.1 christos case lang_reloc_statement_enum:
108 1.1 christos case lang_object_symbols_statement_enum:
109 1.1 christos case lang_output_statement_enum:
110 1.1 christos case lang_target_statement_enum:
111 1.1 christos case lang_input_statement_enum:
112 1.1 christos case lang_assignment_statement_enum:
113 1.1 christos case lang_padding_statement_enum:
114 1.1 christos case lang_address_statement_enum:
115 1.1 christos case lang_fill_statement_enum:
116 1.1 christos break;
117 1.1 christos
118 1.1 christos default:
119 1.1 christos FAIL ();
120 1.1 christos break;
121 1.1 christos }
122 1.1 christos }
123 1.1 christos return FALSE;
124 1.1 christos }
125 1.1 christos
126 1.1 christos /* Create a new stub section called STUB_SEC_NAME and arrange for it to
127 1.1 christos be linked in OUTPUT_SECTION. The section should go at the beginning of
128 1.1 christos OUTPUT_SECTION if INPUT_SECTION is null, otherwise it must go immediately
129 1.1 christos before INPUT_SECTION. */
130 1.1 christos
131 1.1 christos static asection *
132 1.1 christos mips_add_stub_section (const char *stub_sec_name, asection *input_section,
133 1.1 christos asection *output_section)
134 1.1 christos {
135 1.1 christos asection *stub_sec;
136 1.1 christos flagword flags;
137 1.1 christos const char *secname;
138 1.1 christos lang_output_section_statement_type *os;
139 1.1 christos struct hook_stub_info info;
140 1.1 christos
141 1.1 christos /* PR 12845: If the input section has been garbage collected it will
142 1.1 christos not have its output section set to *ABS*. */
143 1.1 christos if (bfd_is_abs_section (output_section))
144 1.1 christos return NULL;
145 1.1 christos
146 1.1 christos /* Create the stub file, if we haven't already. */
147 1.1 christos if (stub_file == NULL)
148 1.1 christos {
149 1.1 christos stub_file = lang_add_input_file ("linker stubs",
150 1.1 christos lang_input_file_is_fake_enum,
151 1.1 christos NULL);
152 1.1 christos stub_bfd = bfd_create ("linker stubs", link_info.output_bfd);
153 1.1 christos if (stub_bfd == NULL
154 1.1 christos || !bfd_set_arch_mach (stub_bfd,
155 1.1 christos bfd_get_arch (link_info.output_bfd),
156 1.1 christos bfd_get_mach (link_info.output_bfd)))
157 1.1 christos {
158 1.1 christos einfo ("%F%P: can not create BFD %E\n");
159 1.1 christos return NULL;
160 1.1 christos }
161 1.1 christos stub_bfd->flags |= BFD_LINKER_CREATED;
162 1.1 christos stub_file->the_bfd = stub_bfd;
163 1.1 christos ldlang_add_file (stub_file);
164 1.1 christos }
165 1.1 christos
166 1.1 christos /* Create the section. */
167 1.1 christos stub_sec = bfd_make_section_anyway (stub_bfd, stub_sec_name);
168 1.1 christos if (stub_sec == NULL)
169 1.1 christos goto err_ret;
170 1.1 christos
171 1.1 christos /* Set the flags. */
172 1.1 christos flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
173 1.1 christos | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
174 1.1 christos if (!bfd_set_section_flags (stub_bfd, stub_sec, flags))
175 1.1 christos goto err_ret;
176 1.1 christos
177 1.1 christos /* Create an output section statement. */
178 1.1 christos secname = bfd_get_section_name (output_section->owner, output_section);
179 1.1 christos os = lang_output_section_find (secname);
180 1.1 christos
181 1.1 christos /* Initialize a statement list that contains only the new statement. */
182 1.1 christos lang_list_init (&info.add);
183 1.1 christos lang_add_section (&info.add, stub_sec, NULL, os);
184 1.1 christos if (info.add.head == NULL)
185 1.1 christos goto err_ret;
186 1.1 christos
187 1.1 christos /* Insert the new statement in the appropriate place. */
188 1.1 christos info.input_section = input_section;
189 1.1 christos if (hook_in_stub (&info, &os->children.head))
190 1.1 christos return stub_sec;
191 1.1 christos
192 1.1 christos err_ret:
193 1.1 christos einfo ("%X%P: can not make stub section: %E\n");
194 1.1 christos return NULL;
195 1.1 christos }
196 1.1 christos
197 1.1 christos /* This is called before the input files are opened. */
198 1.1 christos
199 1.1 christos static void
200 1.1 christos mips_create_output_section_statements (void)
201 1.1 christos {
202 1.1 christos if (is_mips_elf (link_info.output_bfd))
203 1.1 christos _bfd_mips_elf_init_stubs (&link_info, mips_add_stub_section);
204 1.1 christos }
205 1.1 christos
206 1.1 christos /* This is called after we have merged the private data of the input bfds. */
207 1.1 christos
208 1.1 christos static void
209 1.1 christos mips_before_allocation (void)
210 1.1 christos {
211 1.1 christos flagword flags;
212 1.1 christos
213 1.1 christos flags = elf_elfheader (link_info.output_bfd)->e_flags;
214 1.1 christos if (!link_info.shared
215 1.1 christos && !link_info.nocopyreloc
216 1.1 christos && (flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
217 1.1 christos _bfd_mips_elf_use_plts_and_copy_relocs (&link_info);
218 1.1 christos
219 1.1 christos gld${EMULATION_NAME}_before_allocation ();
220 1.1 christos }
221 1.1 christos
222 1.1 christos /* Avoid processing the fake stub_file in vercheck, stat_needed and
223 1.1 christos check_needed routines. */
224 1.1 christos
225 1.1 christos static void (*real_func) (lang_input_statement_type *);
226 1.1 christos
227 1.1 christos static void mips_for_each_input_file_wrapper (lang_input_statement_type *l)
228 1.1 christos {
229 1.1 christos if (l != stub_file)
230 1.1 christos (*real_func) (l);
231 1.1 christos }
232 1.1 christos
233 1.1 christos static void
234 1.1 christos mips_lang_for_each_input_file (void (*func) (lang_input_statement_type *))
235 1.1 christos {
236 1.1 christos real_func = func;
237 1.1 christos lang_for_each_input_file (&mips_for_each_input_file_wrapper);
238 1.1 christos }
239 1.1 christos
240 1.1 christos #define lang_for_each_input_file mips_lang_for_each_input_file
241 1.1 christos
242 1.1 christos EOF
243 1.1 christos
244 1.1 christos LDEMUL_AFTER_PARSE=mips_after_parse
245 1.1 christos LDEMUL_BEFORE_ALLOCATION=mips_before_allocation
246 1.1 christos LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=mips_create_output_section_statements
247