1 # This shell script emits a C file. -*- C -*-
2 # It does some substitutions.
3 cat >e${EMULATION_NAME}.c <<EOF
4 /* This file is is generated by a shell script. DO NOT EDIT! */
6 /* An emulation for HP PA-RISC ELF linkers.
7 Copyright (C) 1991, 93, 94, 95, 97, 99, 2000
8 Free Software Foundation, Inc.
9 Written by Steve Chamberlain steve@cygnus.com
11 This file is part of GLD, the Gnu Linker.
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
41 #include "elf32-hppa.h"
43 static void hppaelf_before_parse PARAMS ((void));
44 static void hppaelf_set_output_arch PARAMS ((void));
45 static void hppaelf_create_output_section_statements PARAMS ((void));
46 static void hppaelf_delete_padding_statements
47 PARAMS ((lang_statement_list_type *list));
48 static void hppaelf_finish PARAMS ((void));
49 static boolean gld${EMULATION_NAME}_place_orphan
50 PARAMS ((lang_input_statement_type *, asection *));
51 static lang_output_section_statement_type *output_rel_find PARAMS ((void));
52 static char *hppaelf_get_script PARAMS ((int *));
55 /* Fake input file for stubs. */
56 static lang_input_statement_type *stub_file;
58 /* Perform some emulation specific initialization. For PA ELF we set
59 up the local label prefix and the output architecture. */
62 hppaelf_before_parse ()
64 ldfile_output_architecture = bfd_arch_hppa;
67 /* Set the output architecture and machine. */
70 hppaelf_set_output_arch()
72 unsigned long machine = 0;
74 bfd_set_arch_mach (output_bfd, ldfile_output_architecture, machine);
77 /* This is called before the input files are opened. We create a new
78 fake input file to hold the stub sections. */
81 hppaelf_create_output_section_statements ()
83 stub_file = lang_add_input_file ("linker stubs",
84 lang_input_file_is_fake_enum,
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)))
92 einfo ("%X%P: can not create BFD %E\n");
96 ldlang_add_file (stub_file);
99 /* Walk all the lang statements splicing out any padding statements from
103 hppaelf_delete_padding_statements (list)
104 lang_statement_list_type *list;
106 lang_statement_union_type *s;
107 lang_statement_union_type **ps;
108 for (ps = &list->head; (s = *ps) != NULL; ps = &s->next)
110 switch (s->header.type)
113 /* We want to recursively walk these sections. */
114 case lang_constructors_statement_enum:
115 hppaelf_delete_padding_statements (&constructor_list);
118 case lang_output_section_statement_enum:
119 hppaelf_delete_padding_statements (&s->output_section_statement.children);
122 case lang_group_statement_enum:
123 hppaelf_delete_padding_statements (&s->group_statement.children);
126 case lang_wild_statement_enum:
127 hppaelf_delete_padding_statements (&s->wild_statement.children);
130 /* Here's what we are really looking for. Splice these out of
132 case lang_padding_statement_enum:
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:
157 struct hook_stub_info
159 lang_statement_list_type add;
160 asection *input_section;
163 /* Traverse the linker tree to find the spot where the stub goes. */
166 hook_in_stub (info, lp)
167 struct hook_stub_info *info;
168 lang_statement_union_type **lp;
170 lang_statement_union_type *l;
173 for (; (l = *lp) != NULL; lp = &l->next)
175 switch (l->header.type)
177 case lang_constructors_statement_enum:
178 ret = hook_in_stub (info, &constructor_list.head);
183 case lang_output_section_statement_enum:
184 ret = hook_in_stub (info,
185 &l->output_section_statement.children.head);
190 case lang_wild_statement_enum:
191 ret = hook_in_stub (info, &l->wild_statement.children.head);
196 case lang_group_statement_enum:
197 ret = hook_in_stub (info, &l->group_statement.children.head);
202 case lang_input_section_enum:
203 if (l->input_section.section == info->input_section)
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;
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:
233 /* Call-back for elf32_hppa_size_stubs. */
235 /* Create a new stub section, and arrange for it to be linked
236 immediately before INPUT_SECTION. */
239 hppaelf_add_stub_section (stub_name, input_section)
240 const char *stub_name;
241 asection *input_section;
245 asection *output_section;
247 lang_output_section_statement_type *os;
248 struct hook_stub_info info;
250 stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_name);
251 if (stub_sec == NULL)
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))
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);
263 info.input_section = input_section;
264 lang_list_init (&info.add);
265 wild_doit (&info.add, stub_sec, os, stub_file);
267 if (info.add.head == NULL)
270 if (hook_in_stub (&info, &os->children.head))
274 einfo ("%X%P: can not make stub section: %E\n");
278 /* Another call-back for elf32_hppa_size_stubs. */
281 hppaelf_layaout_sections_again ()
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. */
287 /* Delete all the padding statements, they're no longer valid. */
288 hppaelf_delete_padding_statements (stat_ptr);
290 /* Resize the sections. */
291 lang_size_sections (stat_ptr->head, abs_output_section,
292 &stat_ptr->head, 0, (bfd_vma) 0, false);
294 /* Redo special stuff. */
295 ldemul_after_allocation ();
297 /* Do the assignments again. */
298 lang_do_assignments (stat_ptr->head, abs_output_section,
299 (fill_type) 0, (bfd_vma) 0);
303 /* Final emulation specific call. For the PA we use this opportunity
304 to build linker stubs. */
309 /* If generating a relocateable output file, then we don't
310 have to examine the relocs. */
311 if (link_info.relocateable)
314 /* Call into the BFD backend to do the real work. */
315 if (elf32_hppa_size_stubs (stub_file->the_bfd,
317 &hppaelf_add_stub_section,
318 &hppaelf_layaout_sections_again) == false)
320 einfo ("%X%P: can not size stub section: %E\n");
324 /* Now build the linker stubs. */
325 if (stub_file->the_bfd->sections != NULL)
327 if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false)
328 einfo ("%X%P: can not build stubs: %E\n");
333 /* Place an orphan section. We use this to put random SHF_ALLOC
334 sections in the right segment. */
338 lang_output_section_statement_type *os;
340 lang_statement_union_type **stmt;
345 gld${EMULATION_NAME}_place_orphan (file, s)
346 lang_input_statement_type *file;
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;
359 const char *secname, *ps;
360 const char *outsecname;
361 lang_output_section_statement_type *os;
363 secname = bfd_get_section_name (s->owner, s);
365 /* Look through the script to see where to place this section. */
366 os = lang_output_section_find (secname);
369 && os->bfd_section != NULL
370 && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0)
372 /* We have already placed a section with this name. */
373 wild_doit (&os->children, s, os, file);
377 if (hold_text.os == NULL)
378 hold_text.os = lang_output_section_find (".text");
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)
387 wild_doit (&hold_text.os->children, s, hold_text.os, file);
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)
399 if (s->flags & SEC_EXCLUDE)
401 else if ((s->flags & SEC_ALLOC) == 0)
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"))
410 else if ((s->flags & SEC_READONLY) == 0
411 && HAVE_SECTION (hold_data, ".data"))
413 else if (strncmp (secname, ".rel", 4) == 0
414 && (hold_rel.os != NULL
415 || (hold_rel.os = output_rel_find ()) != NULL))
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)
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)
439 len = strlen (outsecname);
440 newname = xmalloc (len + 5);
441 strcpy (newname, outsecname);
445 sprintf (newname + len, "%d", i);
448 while (bfd_get_section_by_name (output_bfd, newname) != NULL);
450 outsecname = newname;
455 /* Start building a list of statements for this section. */
458 lang_list_init (stat_ptr);
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 != '_')
465 if (*ps == '\0' && config.build_constructors)
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));
478 if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0)
479 address = exp_intop ((bfd_vma) 0);
483 os = lang_enter_output_section_statement (outsecname, address, 0,
487 (etree_type *) NULL);
489 wild_doit (&os->children, s, os, file);
491 lang_leave_output_section_statement
492 ((bfd_vma) 0, "*default*",
493 (struct lang_output_section_phdr_list *) NULL, "*default*");
497 asection *snew, **pps;
501 if (*ps == '\0' && config.build_constructors)
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, ".")));
512 snew = os->bfd_section;
513 if (place->os->bfd_section != NULL || place->section != NULL)
515 /* Shuffle the section to make the output file look neater. */
516 if (place->section == NULL)
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;
526 place->section = pps;
528 /* Put orphans after the first section on the list. */
529 place->section = &place->os->bfd_section->next;
533 /* Unlink the section. */
534 for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next)
538 /* Now tack it on to the "place->os" section list. */
539 snew->next = *place->section;
540 *place->section = snew;
542 place->section = &snew->next; /* Save the end of this list. */
544 if (place->stmt == NULL)
546 /* Put the new statement list right at the head. */
547 *add.tail = place->os->header.next;
548 place->os->header.next = add.head;
552 /* Put it after the last orphan statement we added. */
553 *add.tail = *place->stmt;
554 *place->stmt = add.head;
556 place->stmt = add.tail; /* Save the end of this list. */
562 /* A variant of lang_output_section_find. */
563 static lang_output_section_statement_type *
566 lang_statement_union_type *u;
567 lang_output_section_statement_type *lookup;
569 for (u = lang_output_section_statement.head;
570 u != (lang_statement_union_type *) NULL;
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)
581 return (lang_output_section_statement_type *) NULL;
584 /* The script itself gets inserted here. */
587 hppaelf_get_script(isfile)
591 if test -n "$COMPILE_IN"
593 # Scripts compiled in.
595 # sed commands to quote an ld script as a C string.
596 sc="-f stringify.sed"
598 cat >>e${EMULATION_NAME}.c <<EOF
602 if (link_info.relocateable == true && config.build_constructors == true)
605 sed $sc ldscripts/${EMULATION_NAME}.xu >> e${EMULATION_NAME}.c
606 echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
607 sed $sc ldscripts/${EMULATION_NAME}.xr >> e${EMULATION_NAME}.c
608 echo ' ; else if (!config.text_read_only) return' >> e${EMULATION_NAME}.c
609 sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c
610 echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c
611 sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c
613 if test -n "$GENERATE_SHLIB_SCRIPT" ; then
614 echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c
615 sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c
618 echo ' ; else return' >> e${EMULATION_NAME}.c
619 sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c
620 echo '; }' >> e${EMULATION_NAME}.c
623 # Scripts read from the filesystem.
625 cat >>e${EMULATION_NAME}.c <<EOF
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";
637 else if (link_info.shared)
638 return "ldscripts/${EMULATION_NAME}.xs";
640 return "ldscripts/${EMULATION_NAME}.x";
646 cat >>e${EMULATION_NAME}.c <<EOF
648 struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
650 hppaelf_before_parse,
655 after_allocation_default,
656 hppaelf_set_output_arch,
657 ldemul_default_target,
658 before_allocation_default,
663 hppaelf_create_output_section_statements,
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 */