* emultempl/hppaelf.em: Include elf32-hppa.h.
[deliverable/binutils-gdb.git] / ld / emultempl / ppc.em
CommitLineData
c361ce46
ILT
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3cat >em_${EMULATION_NAME}.c <<EOF
4/* This file is is generated by a shell script. DO NOT EDIT! */
5
6/* PowerPC/POWER emulation for the linker.
7 Copyright (C) 1994 Free Software Foundation, Inc.
8 Written by Ian Lance Taylor, Cygnus Support
9
10This file is part of GLD, the Gnu Linker.
11
12This program is free software; you can redistribute it and/or modify
13it under the terms of the GNU General Public License as published by
14the Free Software Foundation; either version 2 of the License, or
15(at your option) any later version.
16
17This program is distributed in the hope that it will be useful,
18but WITHOUT ANY WARRANTY; without even the implied warranty of
19MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
25
26/* This file is similar to generic.em. However, we need to build
27 linker stubs to handle calls to different modules. A PowerPC call
28 is emitted as a two instruction sequence:
29 bl .{function}
30 cror 31,31,31
31
32 When linking, if the function symbol is defined and in the same
33 module, we leave it alone (actually, if it is more than 26 bits
34 away we should treat it as though it were in a different module).
35 If the function symbol is not defined, we must construct a linker
36 stub. We reroute the call to go to the linker stub instead, and we
37 change the cror instruction to reload the TOC register value. The
38 linker stub looks like this
39 l r12,{function}(r2)
40 st r2,20(r1)
41 l r0,0(r12)
42 l r2,4(r12)
43 mtctr r0
44 bcc
45
46 Since we do not yet support dynamic linking, all function symbols
47 are in the same module. However, we still need to create a stub
48 for an undefined symbol.
49
50 This is actually probably not correct for the PowerPC ABI.
51 However, I do not have that ABI yet. */
52
53#define TARGET_IS_${EMULATION_NAME}
54
55#include "bfd.h"
56#include "sysdep.h"
57#include "bfdlink.h"
58
59/* FIXME! */
60#include "genlink.h"
61
62#include "ld.h"
63#include "config.h"
64#include "ldmain.h"
65#include "ldemul.h"
66#include "ldfile.h"
67#include "ldmisc.h"
68#include "ldexp.h"
69#include "ldlang.h"
70
71static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
72static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
73static void gld${EMULATION_NAME}_create_output_section_statements
74 PARAMS ((void));
75static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
76static boolean gld${EMULATION_NAME}_check_symbol
77 PARAMS ((struct bfd_link_hash_entry *, PTR));
78
79static void
80gld${EMULATION_NAME}_before_parse()
81{
82 ldfile_output_architecture = bfd_arch_${ARCH};
83}
84
85/* Section in which we build stubs. */
86
87static asection *stub_sec;
88
89/* Section in which we build TOC entries for stubs. */
90
91static asection *stub_toc_sec;
92
93/* This is called before the input files are opened. We create a new
94 fake input file to hold the stub section. */
95
96static void
97gld${EMULATION_NAME}_create_output_section_statements ()
98{
99 lang_input_statement_type *stub_file;
100
101 stub_file = lang_add_input_file ("linker stubs",
102 lang_input_file_is_fake_enum,
103 (char *) NULL);
104
105 stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
106 if (stub_file->the_bfd == (bfd *) NULL
107 || ! bfd_set_arch_mach (stub_file->the_bfd,
108 bfd_get_arch (output_bfd),
109 bfd_get_mach (output_bfd)))
110 {
111 einfo ("%X%P: can not create BFD: %E");
112 return;
113 }
114
115 stub_sec = bfd_make_section_old_way (stub_file->the_bfd, ".text");
116 stub_toc_sec = bfd_make_section_old_way (stub_file->the_bfd, ".toc");
117 if (stub_sec == (asection *) NULL
118 || stub_toc_sec == (asection *) NULL
119 || ! bfd_set_section_flags (stub_file->the_bfd, stub_sec,
120 (SEC_HAS_CONTENTS
121 | SEC_ALLOC
122 | SEC_LOAD
123 | SEC_CODE
124 | SEC_RELOC
125 | SEC_IN_MEMORY))
126 || ! bfd_set_section_flags (stub_file->the_bfd, stub_toc_sec,
127 (SEC_HAS_CONTENTS
128 | SEC_ALLOC
129 | SEC_LOAD
130 | SEC_DATA
131 | SEC_RELOC
132 | SEC_IN_MEMORY)))
133 {
134 einfo ("%X%P: can not create stub sections: %E");
135 return;
136 }
137
138 ldlang_add_file (stub_file);
139}
140
141/* This is called after the input sections have been attached to the
142 output sections but before the output section sizes have been set.
143 We can identify the required stubs because they are undefined
144 symbols beginning with ".". For each such symbol, we build a stub
145 in the .text section. */
146
147static void
148gld${EMULATION_NAME}_before_allocation ()
149{
150 bfd_link_hash_traverse (link_info.hash,
151 gld${EMULATION_NAME}_check_symbol,
152 (PTR) NULL);
153}
154
155/* If a particular symbol is undefined and starts with a ".", then we
156 need to make a stub for it. */
157
158/*ARGSUSED*/
159static boolean
160gld${EMULATION_NAME}_check_symbol (h, info)
161 struct bfd_link_hash_entry *h;
162 PTR info;
163{
164 bfd *stub_bfd;
165 bfd_byte *p;
166 arelent *r;
167 struct bfd_link_hash_entry *hnew;
168 asymbol *sym;
169
170 if (h->type != bfd_link_hash_undefined
171 || h->root.string[0] != '.')
172 return true;
173
174 stub_bfd = stub_sec->owner;
175
176 /* Define this symbol to be the current location in stub_sec. */
177 h->type = bfd_link_hash_defined;
178 h->u.def.value = bfd_section_size (stub_bfd, stub_sec);
179 h->u.def.section = stub_sec;
180
181 /* We want to add this:
182 LONG (0x81820000) lwz r12,{TOC index}(r2)
183 LONG (0x90410014) stw r2,20(r1)
184 LONG (0x800c0000) lwz r0,0(r12)
185 LONG (0x804c0004) lwz r2,4(r12)
186 LONG (0x7c0903a6) mtctr r0
187 LONG (0x4e800420) bctr
188 LONG (0) Traceback table
189 LONG (0xc8000)
190 LONG (0)
191 */
192
193 if (! bfd_set_section_size (stub_bfd, stub_sec,
194 h->u.def.value + 9 * 4))
195 {
196 einfo ("%P%X: can not set section size: %E");
197 return false;
198 }
199
200 stub_sec->contents = ((bfd_byte *)
201 xrealloc ((PTR) stub_sec->contents,
202 bfd_section_size (stub_bfd, stub_sec)));
203 p = stub_sec->contents + h->u.def.value;
204 bfd_put_32 (stub_bfd,
205 (bfd_vma) 0x81820000 + bfd_section_size (stub_bfd, stub_toc_sec),
206 p);
207 p += 4;
208 bfd_put_32 (stub_bfd, (bfd_vma) 0x90410014, p);
209 p += 4;
210 bfd_put_32 (stub_bfd, (bfd_vma) 0x800c0000, p);
211 p += 4;
212 bfd_put_32 (stub_bfd, (bfd_vma) 0x804c0004, p);
213 p += 4;
214 bfd_put_32 (stub_bfd, (bfd_vma) 0x7c0903a6, p);
215 p += 4;
216 bfd_put_32 (stub_bfd, (bfd_vma) 0x4e800420, p);
217 p += 4;
218 bfd_put_32 (stub_bfd, (bfd_vma) 0, p);
219 p += 4;
220 bfd_put_32 (stub_bfd, (bfd_vma) 0xc8000, p);
221 p += 4;
222 bfd_put_32 (stub_bfd, (bfd_vma) 0, p);
223
224 /* Add an undefined symbol for the TOC reference. This is the name
225 without the leading ".". */
226 hnew = bfd_link_hash_lookup (link_info.hash, h->root.string + 1, true,
227 false, true);
228 if (hnew == (struct bfd_link_hash_entry *) NULL)
229 einfo ("%P%F: bfd_link_hash_lookup failed: %E");
230 if (hnew->type == bfd_link_hash_new)
231 {
232 hnew->type = bfd_link_hash_undefined;
233 hnew->u.undef.abfd = stub_bfd;
234 bfd_link_add_undef (link_info.hash, hnew);
235 }
236
237 /* Add a relocation entry for the TOC reference in the first
238 instruction. */
239 ++stub_sec->reloc_count;
240 stub_sec->relocation = ((arelent *)
241 xrealloc ((PTR) stub_sec->relocation,
242 (stub_sec->reloc_count
243 * sizeof (arelent))));
244 r = &stub_sec->relocation[stub_sec->reloc_count - 1];
245 r->sym_ptr_ptr = stub_toc_sec->symbol_ptr_ptr;
246 r->address = h->u.def.value;
247 if (stub_bfd->xvec->byteorder_big_p)
248 r->address += 2;
249 r->addend = 0;
250 r->howto = bfd_reloc_type_lookup (stub_bfd, BFD_RELOC_PPC_TOC16);
251 if (r->howto == (reloc_howto_type *) NULL)
252 einfo ("%P%F: no howto for TOC reference: %E");
253
254 /* Add a relocation entry in the TOC section. */
255 ++stub_toc_sec->reloc_count;
256 stub_toc_sec->relocation = ((arelent *)
257 xrealloc ((PTR) stub_toc_sec->relocation,
258 (stub_toc_sec->reloc_count
259 * sizeof (arelent))));
260 r = &stub_toc_sec->relocation[stub_toc_sec->reloc_count - 1];
261
262 sym = bfd_make_empty_symbol (stub_bfd);
263 sym->name = hnew->root.string;
264 sym->value = 0;
265 sym->flags = BSF_NO_FLAGS;
266 sym->section = &bfd_und_section;
267 sym->udata = NULL;
268
269 /* FIXME! */
270 ((struct generic_link_hash_entry *) hnew)->sym = sym;
271
272 r->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
273 *r->sym_ptr_ptr = sym;
274 r->address = bfd_section_size (stub_bfd, stub_toc_sec);
275 r->addend = 0;
276 r->howto = bfd_reloc_type_lookup (stub_bfd, BFD_RELOC_32);
277 if (r->howto == (reloc_howto_type *) NULL)
278 einfo ("%P%F: no howto for TOC entry: %E");
279
280 /* Add more space to the .toc section. */
281 if (! bfd_set_section_size (stub_bfd, stub_toc_sec,
282 bfd_section_size (stub_bfd, stub_toc_sec) + 4))
283 {
284 einfo ("%P%X: can not set section size: %E");
285 return false;
286 }
287
288 stub_toc_sec->contents = ((bfd_byte *)
289 xrealloc ((PTR) stub_toc_sec->contents,
290 bfd_section_size (stub_bfd,
291 stub_toc_sec)));
292 bfd_put_32 (stub_bfd, (bfd_vma) 0,
293 (stub_toc_sec->contents
294 + bfd_section_size (stub_bfd, stub_toc_sec)
295 - 4));
296
297 return true;
298}
299
300static char *
301gld${EMULATION_NAME}_get_script(isfile)
302 int *isfile;
303EOF
304
305if test -n "$COMPILE_IN"
306then
307# Scripts compiled in.
308
309# sed commands to quote an ld script as a C string.
310sc='s/["\\]/\\&/g
311s/$/\\n\\/
3de3daca
ILT
3121s/^/"/
313$s/$/n"/
c361ce46
ILT
314'
315
316cat >>em_${EMULATION_NAME}.c <<EOF
317{
318 *isfile = 0;
319
320 if (link_info.relocateable == true && config.build_constructors == true)
321 return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
322 else if (link_info.relocateable == true)
323 return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
324 else if (!config.text_read_only)
325 return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
326 else if (!config.magic_demand_paged)
327 return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
328 else
329 return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
330}
331EOF
332
333else
334# Scripts read from the filesystem.
335
336cat >>em_${EMULATION_NAME}.c <<EOF
337{
338 *isfile = 1;
339
340 if (link_info.relocateable == true && config.build_constructors == true)
341 return "ldscripts/${EMULATION_NAME}.xu";
342 else if (link_info.relocateable == true)
343 return "ldscripts/${EMULATION_NAME}.xr";
344 else if (!config.text_read_only)
345 return "ldscripts/${EMULATION_NAME}.xbn";
346 else if (!config.magic_demand_paged)
347 return "ldscripts/${EMULATION_NAME}.xn";
348 else
349 return "ldscripts/${EMULATION_NAME}.x";
350}
351EOF
352
353fi
354
355cat >>em_${EMULATION_NAME}.c <<EOF
356
357struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
358{
359 gld${EMULATION_NAME}_before_parse,
360 syslib_default,
361 hll_default,
362 after_parse_default,
363 after_allocation_default,
364 set_output_arch_default,
365 ldemul_default_target,
366 gld${EMULATION_NAME}_before_allocation,
367 gld${EMULATION_NAME}_get_script,
368 "${EMULATION_NAME}",
369 "${OUTPUT_FORMAT}",
370 0,
371 gld${EMULATION_NAME}_create_output_section_statements
372};
373EOF
This page took 0.03662 seconds and 4 git commands to generate.