Move functions around in preparation for next patch
[deliverable/binutils-gdb.git] / ld / emultempl / hppaelf.em
CommitLineData
252b5132
RH
1# This shell script emits a C file. -*- C -*-
2# It does some substitutions.
3cat >e${EMULATION_NAME}.c <<EOF
4900fc06
AM
4/* This file is is generated by a shell script. DO NOT EDIT! */
5
252b5132 6/* An emulation for HP PA-RISC ELF linkers.
4900fc06
AM
7 Copyright (C) 1991, 93, 94, 95, 97, 99, 2000
8 Free Software Foundation, Inc.
252b5132
RH
9 Written by Steve Chamberlain steve@cygnus.com
10
11This file is part of GLD, the Gnu Linker.
12
13This program is free software; you can redistribute it and/or modify
14it under the terms of the GNU General Public License as published by
15the Free Software Foundation; either version 2 of the License, or
16(at your option) any later version.
17
18This program is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License
24along with this program; if not, write to the Free Software
25Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
26
27#include "bfd.h"
28#include "sysdep.h"
4900fc06 29#include <ctype.h>
252b5132
RH
30#include "bfdlink.h"
31
32#include "ld.h"
4900fc06 33#include "ldmain.h"
4900fc06 34#include "ldmisc.h"
252b5132
RH
35#include "ldexp.h"
36#include "ldlang.h"
b71e2778
AM
37#include "ldfile.h"
38#include "ldemul.h"
4900fc06 39#include "ldgram.h"
252b5132 40#include "ldctor.h"
4900fc06 41#include "elf32-hppa.h"
252b5132 42
4900fc06
AM
43static void hppaelf_before_parse PARAMS ((void));
44static void hppaelf_set_output_arch PARAMS ((void));
45static void hppaelf_create_output_section_statements PARAMS ((void));
46static void hppaelf_delete_padding_statements
47 PARAMS ((lang_statement_list_type *list));
48static void hppaelf_finish PARAMS ((void));
49static boolean gld${EMULATION_NAME}_place_orphan
50 PARAMS ((lang_input_statement_type *, asection *));
51static lang_output_section_statement_type *output_rel_find PARAMS ((void));
52static char *hppaelf_get_script PARAMS ((int *));
252b5132
RH
53
54
4900fc06
AM
55/* Fake input file for stubs. */
56static lang_input_statement_type *stub_file;
252b5132
RH
57
58/* Perform some emulation specific initialization. For PA ELF we set
59 up the local label prefix and the output architecture. */
60
61static void
62hppaelf_before_parse ()
63{
64 ldfile_output_architecture = bfd_arch_hppa;
65}
66
67/* Set the output architecture and machine. */
68
69static void
70hppaelf_set_output_arch()
71{
72 unsigned long machine = 0;
73
74 bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine);
75}
76
77/* This is called before the input files are opened. We create a new
4900fc06 78 fake input file to hold the stub sections. */
252b5132
RH
79
80static void
81hppaelf_create_output_section_statements ()
82{
83 stub_file = lang_add_input_file ("linker stubs",
84 lang_input_file_is_fake_enum,
85 NULL);
86 stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
87 if (stub_file->the_bfd == NULL
88 || ! bfd_set_arch_mach (stub_file->the_bfd,
89 bfd_get_arch (output_bfd),
90 bfd_get_mach (output_bfd)))
91 {
92 einfo ("%X%P: can not create BFD %E\n");
93 return;
94 }
95
252b5132
RH
96 ldlang_add_file (stub_file);
97}
98
4900fc06 99/* Walk all the lang statements splicing out any padding statements from
252b5132
RH
100 the list. */
101
102static void
4900fc06
AM
103hppaelf_delete_padding_statements (list)
104 lang_statement_list_type *list;
252b5132 105{
4900fc06
AM
106 lang_statement_union_type *s;
107 lang_statement_union_type **ps;
108 for (ps = &list->head; (s = *ps) != NULL; ps = &s->next)
252b5132
RH
109 {
110 switch (s->header.type)
111 {
112
4900fc06 113 /* We want to recursively walk these sections. */
252b5132 114 case lang_constructors_statement_enum:
4900fc06 115 hppaelf_delete_padding_statements (&constructor_list);
252b5132
RH
116 break;
117
118 case lang_output_section_statement_enum:
4900fc06
AM
119 hppaelf_delete_padding_statements (&s->output_section_statement.children);
120 break;
121
122 case lang_group_statement_enum:
123 hppaelf_delete_padding_statements (&s->group_statement.children);
252b5132
RH
124 break;
125
252b5132 126 case lang_wild_statement_enum:
4900fc06 127 hppaelf_delete_padding_statements (&s->wild_statement.children);
252b5132
RH
128 break;
129
130 /* Here's what we are really looking for. Splice these out of
131 the list. */
132 case lang_padding_statement_enum:
4900fc06
AM
133 *ps = s->next;
134 if (*ps == NULL)
135 list->tail = ps;
252b5132
RH
136 break;
137
138 /* We don't care about these cases. */
139 case lang_data_statement_enum:
140 case lang_object_symbols_statement_enum:
141 case lang_output_statement_enum:
142 case lang_target_statement_enum:
143 case lang_input_section_enum:
144 case lang_input_statement_enum:
145 case lang_assignment_statement_enum:
146 case lang_address_statement_enum:
147 break;
148
149 default:
150 abort ();
151 break;
152 }
252b5132
RH
153 }
154}
155
4900fc06
AM
156
157struct hook_stub_info
158{
159 lang_statement_list_type add;
160 asection *input_section;
161};
162
163/* Traverse the linker tree to find the spot where the stub goes. */
164
165static boolean
166hook_in_stub (info, lp)
167 struct hook_stub_info *info;
168 lang_statement_union_type **lp;
169{
170 lang_statement_union_type *l;
171 boolean ret;
172
173 for (; (l = *lp) != NULL; lp = &l->next)
174 {
175 switch (l->header.type)
176 {
177 case lang_constructors_statement_enum:
178 ret = hook_in_stub (info, &constructor_list.head);
179 if (ret)
180 return ret;
181 break;
182
183 case lang_output_section_statement_enum:
184 ret = hook_in_stub (info,
185 &l->output_section_statement.children.head);
186 if (ret)
187 return ret;
188 break;
189
190 case lang_wild_statement_enum:
191 ret = hook_in_stub (info, &l->wild_statement.children.head);
192 if (ret)
193 return ret;
194 break;
195
196 case lang_group_statement_enum:
197 ret = hook_in_stub (info, &l->group_statement.children.head);
198 if (ret)
199 return ret;
200 break;
201
202 case lang_input_section_enum:
203 if (l->input_section.section == info->input_section)
204 {
205 /* We've found our section. Insert the stub immediately
206 before its associated input section. */
207 *lp = info->add.head;
208 *(info->add.tail) = l;
209 return true;
210 }
211 break;
212
213 case lang_data_statement_enum:
214 case lang_reloc_statement_enum:
215 case lang_object_symbols_statement_enum:
216 case lang_output_statement_enum:
217 case lang_target_statement_enum:
218 case lang_input_statement_enum:
219 case lang_assignment_statement_enum:
220 case lang_padding_statement_enum:
221 case lang_address_statement_enum:
222 case lang_fill_statement_enum:
223 break;
224
225 default:
226 FAIL ();
227 break;
228 }
229 }
230 return false;
231}
232
233/* Call-back for elf32_hppa_size_stubs. */
234
235/* Create a new stub section, and arrange for it to be linked
236 immediately before INPUT_SECTION. */
237
238static asection *
239hppaelf_add_stub_section (stub_name, input_section)
240 const char *stub_name;
241 asection *input_section;
242{
243 asection *stub_sec;
244 flagword flags;
245 asection *output_section;
246 const char *secname;
247 lang_output_section_statement_type *os;
248 struct hook_stub_info info;
249
250 stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_name);
251 if (stub_sec == NULL)
252 goto err_ret;
253
254 flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
255 | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
256 if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags))
257 goto err_ret;
258
259 output_section = input_section->output_section;
260 secname = bfd_get_section_name (output_section->owner, output_section);
261 os = lang_output_section_find (secname);
262
263 info.input_section = input_section;
264 lang_list_init (&info.add);
265 wild_doit (&info.add, stub_sec, os, stub_file);
266
267 if (info.add.head == NULL)
268 goto err_ret;
269
270 if (hook_in_stub (&info, &os->children.head))
271 return stub_sec;
272
273 err_ret:
274 einfo ("%X%P: can not make stub section: %E\n");
275 return NULL;
276}
277
278/* Another call-back for elf32_hppa_size_stubs. */
279
280static void
281hppaelf_layaout_sections_again ()
282{
283 /* If we have changed sizes of the stub sections, then we need
284 to recalculate all the section offsets. This may mean we need to
285 add even more stubs. */
286
287 /* Delete all the padding statements, they're no longer valid. */
288 hppaelf_delete_padding_statements (stat_ptr);
289
290 /* Resize the sections. */
291 lang_size_sections (stat_ptr->head, abs_output_section,
292 &stat_ptr->head, 0, (bfd_vma) 0, false);
293
294 /* Redo special stuff. */
295 ldemul_after_allocation ();
296
297 /* Do the assignments again. */
298 lang_do_assignments (stat_ptr->head, abs_output_section,
299 (fill_type) 0, (bfd_vma) 0);
300}
301
302
252b5132
RH
303/* Final emulation specific call. For the PA we use this opportunity
304 to build linker stubs. */
305
306static void
307hppaelf_finish ()
308{
4900fc06
AM
309 /* If generating a relocateable output file, then we don't
310 have to examine the relocs. */
311 if (link_info.relocateable)
312 return;
313
252b5132 314 /* Call into the BFD backend to do the real work. */
4900fc06
AM
315 if (elf32_hppa_size_stubs (stub_file->the_bfd,
316 &link_info,
317 &hppaelf_add_stub_section,
318 &hppaelf_layaout_sections_again) == false)
252b5132
RH
319 {
320 einfo ("%X%P: can not size stub section: %E\n");
321 return;
322 }
4900fc06
AM
323
324 /* Now build the linker stubs. */
325 if (stub_file->the_bfd->sections != NULL)
252b5132 326 {
252b5132 327 if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false)
4900fc06
AM
328 einfo ("%X%P: can not build stubs: %E\n");
329 }
330}
331
332
333/* Place an orphan section. We use this to put random SHF_ALLOC
334 sections in the right segment. */
335
336struct orphan_save
337{
338 lang_output_section_statement_type *os;
339 asection **section;
340 lang_statement_union_type **stmt;
341};
342
343/*ARGSUSED*/
344static boolean
345gld${EMULATION_NAME}_place_orphan (file, s)
346 lang_input_statement_type *file;
347 asection *s;
348{
349 static struct orphan_save hold_text;
350 static struct orphan_save hold_rodata;
351 static struct orphan_save hold_data;
352 static struct orphan_save hold_bss;
353 static struct orphan_save hold_rel;
354 static struct orphan_save hold_interp;
355 struct orphan_save *place;
356 lang_statement_list_type *old;
357 lang_statement_list_type add;
358 etree_type *address;
359 const char *secname, *ps;
360 const char *outsecname;
361 lang_output_section_statement_type *os;
362
363 secname = bfd_get_section_name (s->owner, s);
364
365 /* Look through the script to see where to place this section. */
366 os = lang_output_section_find (secname);
367
368 if (os != NULL
369 && os->bfd_section != NULL
370 && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
371 {
372 /* We have already placed a section with this name. */
373 wild_doit (&os->children, s, os, file);
374 return true;
375 }
376
377 if (hold_text.os == NULL)
378 hold_text.os = lang_output_section_find (".text");
379
380 /* If this is a final link, then always put .gnu.warning.SYMBOL
381 sections into the .text section to get them out of the way. */
382 if (! link_info.shared
383 && ! link_info.relocateable
384 && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0
385 && hold_text.os != NULL)
386 {
387 wild_doit (&hold_text.os->children, s, hold_text.os, file);
388 return true;
389 }
390
391 /* Decide which segment the section should go in based on the
392 section name and section flags. We put loadable .note sections
393 right after the .interp section, so that the PT_NOTE segment is
394 stored right after the program headers where the OS can read it
395 in the first page. */
396#define HAVE_SECTION(hold, name) \
397(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL)
398
399 if (s->flags & SEC_EXCLUDE)
400 return false;
401 else if ((s->flags & SEC_ALLOC) == 0)
402 place = NULL;
403 else if ((s->flags & SEC_LOAD) != 0
404 && strncmp (secname, ".note", 4) == 0
405 && HAVE_SECTION (hold_interp, ".interp"))
406 place = &hold_interp;
407 else if ((s->flags & SEC_HAS_CONTENTS) == 0
408 && HAVE_SECTION (hold_bss, ".bss"))
409 place = &hold_bss;
410 else if ((s->flags & SEC_READONLY) == 0
411 && HAVE_SECTION (hold_data, ".data"))
412 place = &hold_data;
413 else if (strncmp (secname, ".rel", 4) == 0
414 && (hold_rel.os != NULL
415 || (hold_rel.os = output_rel_find ()) != NULL))
416 place = &hold_rel;
417 else if ((s->flags & SEC_CODE) == 0
418 && (s->flags & SEC_READONLY) != 0
419 && HAVE_SECTION (hold_rodata, ".rodata"))
420 place = &hold_rodata;
421 else if ((s->flags & SEC_READONLY) != 0
422 && hold_text.os != NULL)
423 place = &hold_text;
424 else
425 place = NULL;
426
427#undef HAVE_SECTION
428
429 /* Choose a unique name for the section. This will be needed if the
430 same section name appears in the input file with different
431 loadable or allocateable characteristics. */
432 outsecname = secname;
433 if (bfd_get_section_by_name (output_bfd, outsecname) != NULL)
434 {
435 unsigned int len;
436 char *newname;
437 unsigned int i;
438
439 len = strlen (outsecname);
440 newname = xmalloc (len + 5);
441 strcpy (newname, outsecname);
442 i = 0;
443 do
444 {
445 sprintf (newname + len, "%d", i);
446 ++i;
447 }
448 while (bfd_get_section_by_name (output_bfd, newname) != NULL);
449
450 outsecname = newname;
451 }
452
453 if (place != NULL)
454 {
455 /* Start building a list of statements for this section. */
456 old = stat_ptr;
457 stat_ptr = &add;
458 lang_list_init (stat_ptr);
459
460 /* If the name of the section is representable in C, then create
461 symbols to mark the start and the end of the section. */
462 for (ps = outsecname; *ps != '\0'; ps++)
463 if (! isalnum ((unsigned char) *ps) && *ps != '_')
464 break;
465 if (*ps == '\0' && config.build_constructors)
252b5132 466 {
4900fc06
AM
467 char *symname;
468 etree_type *e_align;
469
470 symname = (char *) xmalloc (ps - outsecname + sizeof "__start_");
471 sprintf (symname, "__start_%s", outsecname);
472 e_align = exp_unop (ALIGN_K,
473 exp_intop ((bfd_vma) 1 << s->alignment_power));
474 lang_add_assignment (exp_assop ('=', symname, e_align));
252b5132
RH
475 }
476 }
4900fc06
AM
477
478 if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
479 address = exp_intop ((bfd_vma) 0);
480 else
481 address = NULL;
482
483 os = lang_enter_output_section_statement (outsecname, address, 0,
484 (bfd_vma) 0,
485 (etree_type *) NULL,
486 (etree_type *) NULL,
487 (etree_type *) NULL);
488
489 wild_doit (&os->children, s, os, file);
490
491 lang_leave_output_section_statement
492 ((bfd_vma) 0, "*default*",
493 (struct lang_output_section_phdr_list *) NULL, "*default*");
494
495 if (place != NULL)
496 {
497 asection *snew, **pps;
498
499 stat_ptr = &add;
500
501 if (*ps == '\0' && config.build_constructors)
502 {
503 char *symname;
504
505 symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_");
506 sprintf (symname, "__stop_%s", outsecname);
507 lang_add_assignment (exp_assop ('=', symname,
508 exp_nameop (NAME, ".")));
509 }
510 stat_ptr = old;
511
512 snew = os->bfd_section;
513 if (place->os->bfd_section != NULL || place->section != NULL)
514 {
515 /* Shuffle the section to make the output file look neater. */
516 if (place->section == NULL)
517 {
518#if 0
519 /* Finding the end of the list is a little tricky. We
520 make a wild stab at it by comparing section flags. */
521 flagword first_flags = place->os->bfd_section->flags;
522 for (pps = &place->os->bfd_section->next;
523 *pps != NULL && (*pps)->flags == first_flags;
524 pps = &(*pps)->next)
525 ;
526 place->section = pps;
527#else
528 /* Put orphans after the first section on the list. */
529 place->section = &place->os->bfd_section->next;
530#endif
531 }
532
533 /* Unlink the section. */
534 for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
535 ;
536 *pps = snew->next;
537
538 /* Now tack it on to the "place->os" section list. */
539 snew->next = *place->section;
540 *place->section = snew;
541 }
542 place->section = &snew->next; /* Save the end of this list. */
543
544 if (place->stmt == NULL)
545 {
546 /* Put the new statement list right at the head. */
547 *add.tail = place->os->header.next;
548 place->os->header.next = add.head;
549 }
550 else
551 {
552 /* Put it after the last orphan statement we added. */
553 *add.tail = *place->stmt;
554 *place->stmt = add.head;
555 }
556 place->stmt = add.tail; /* Save the end of this list. */
557 }
558
559 return true;
560}
561
562/* A variant of lang_output_section_find. */
563static lang_output_section_statement_type *
564output_rel_find ()
565{
566 lang_statement_union_type *u;
567 lang_output_section_statement_type *lookup;
568
569 for (u = lang_output_section_statement.head;
570 u != (lang_statement_union_type *) NULL;
571 u = lookup->next)
572 {
573 lookup = &u->output_section_statement;
574 if (strncmp (".rel", lookup->name, 4) == 0
575 && lookup->bfd_section != NULL
576 && (lookup->bfd_section->flags & SEC_ALLOC) != 0)
577 {
578 return lookup;
579 }
580 }
581 return (lang_output_section_statement_type *) NULL;
252b5132
RH
582}
583
584/* The script itself gets inserted here. */
585
586static char *
587hppaelf_get_script(isfile)
588 int *isfile;
589EOF
590
591if test -n "$COMPILE_IN"
592then
593# Scripts compiled in.
594
595# sed commands to quote an ld script as a C string.
597e2591 596sc="-f stringify.sed"
252b5132
RH
597
598cat >>e${EMULATION_NAME}.c <<EOF
4900fc06 599{
252b5132
RH
600 *isfile = 0;
601
602 if (link_info.relocateable == true && config.build_constructors == true)
597e2591 603 return
252b5132 604EOF
597e2591
ILT
605sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
606echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
607sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
608echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
609sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
610echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
611sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
4900fc06
AM
612
613if test -n "$GENERATE_SHLIB_SCRIPT" ; then
614echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
615sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
616fi
617
597e2591
ILT
618echo ' ; else return' >> e${EMULATION_NAME}.c
619sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
620echo '; }' >> e${EMULATION_NAME}.c
252b5132
RH
621
622else
623# Scripts read from the filesystem.
624
625cat >>e${EMULATION_NAME}.c <<EOF
626{
627 *isfile = 1;
628
629 if (link_info.relocateable == true && config.build_constructors == true)
630 return "ldscripts/${EMULATION_NAME}.xu";
631 else if (link_info.relocateable == true)
632 return "ldscripts/${EMULATION_NAME}.xr";
633 else if (!config.text_read_only)
634 return "ldscripts/${EMULATION_NAME}.xbn";
635 else if (!config.magic_demand_paged)
636 return "ldscripts/${EMULATION_NAME}.xn";
4900fc06
AM
637 else if (link_info.shared)
638 return "ldscripts/${EMULATION_NAME}.xs";
252b5132
RH
639 else
640 return "ldscripts/${EMULATION_NAME}.x";
641}
642EOF
643
644fi
645
646cat >>e${EMULATION_NAME}.c <<EOF
647
4900fc06 648struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
252b5132
RH
649{
650 hppaelf_before_parse,
651 syslib_default,
652 hll_default,
653 after_parse_default,
654 after_open_default,
655 after_allocation_default,
656 hppaelf_set_output_arch,
657 ldemul_default_target,
658 before_allocation_default,
659 hppaelf_get_script,
4900fc06 660 "${EMULATION_NAME}",
252b5132
RH
661 "elf32-hppa",
662 hppaelf_finish,
663 hppaelf_create_output_section_statements,
4900fc06
AM
664 NULL, /* open dynamic */
665 gld${EMULATION_NAME}_place_orphan,
666 NULL, /* set_symbols */
667 NULL, /* parse_args */
668 NULL, /* unrecognized_file */
669 NULL, /* list_options */
670 NULL, /* recognized_file */
671 NULL /* find_potential_libraries */
252b5132
RH
672};
673EOF
This page took 0.173445 seconds and 4 git commands to generate.