From 23b4616e9e6ae462a00e9e6232dd4bd0a6705eff Mon Sep 17 00:00:00 2001 From: amodra Date: Sun, 9 Jul 2000 08:45:29 +0000 Subject: [PATCH] hppaelf.em: Merge from elf32.em and implement multiple linker stubs. Makefile.am: Re-enable ehppaelf.o, add ehppalinux.o configure.tgt: targ_emul=hppalinux for hppa*linux --- ld/ChangeLog | 46 ++++ ld/Makefile.am | 51 +++-- ld/Makefile.in | 53 ++--- ld/configure.tgt | 1 + ld/emulparams/hppaelf.sh | 2 +- ld/emulparams/hppalinux.sh | 10 + ld/emultempl/hppaelf.em | 551 ++++++++++++++++++++++++++++++++++++++------- 7 files changed, 579 insertions(+), 135 deletions(-) create mode 100644 ld/emulparams/hppalinux.sh diff --git a/ld/ChangeLog b/ld/ChangeLog index 4109d25c53..bffdd5dc52 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,49 @@ +2000-07-09 Alan Modra + + Changes to create multiple linker stubs, positioned immediately + before the section where they are required. + * emultempl/hppaelf.em: Include elf32-hppa.h. + (stub_sec, file_chain): Delete. + (hppaelf_create_output_section_statements): Don't make a stub + section here. + (hook_stub_info): New struct. + (hook_in_stub): New function. + (hppaelf_add_stub_section): New function. + (hppaelf_finish): Do nothing for relocateable links. Modify the + call to elf32_hppa_size_stubs. Move code for updating section + layout from here... + (hppaelf_layaout_sections_again): ..to here, a new function. + + * emultempl/hppaelf.em (hppaelf_delete_padding_statements): Fix + broken list handling. Pass in a pointer to the list. + (hppaelf_finish): Update call to hppaelf_delete_padding_statements + for above changes. + (hppaelf_before_parse): Prototype. + (hppaelf_set_output_arch): Prototype. + (hppaelf_create_output_section_statements): Prototype. + (hppaelf_delete_padding_statements): Prototype. + (hppaelf_finish): Prototype. + + Merge from elf32.em + * emultempl/hppaelf.em: Include ctype.h. + (struct orphan_save): New. + (gld${EMULATION_NAME}_place_orphan): New. + (output_rel_find): New. + (hppaelf_get_script): Update from elf32.em. + (ld_hppaelf_emulation): Rename to ld_${EMULATION_NAME}_emulation. + Change emulation_name field to "${EMULATION_NAME}". Add + gld${EMULATION_NAME}_place_orphan. + + * Makefile.am (ALL_EMULATIONS): Reinstate ehppaelf.o, add + ehppalinux.o, sort it. Regenerate dependencies. + (ehppalinux.c): Depend on hppaelf.em + * Makefile.in: Regenerate. + + * configure.tgt: targ_emul=hppalinux for hppa*linux + + * emulparams/hppalinux.sh: New. + * emulparams/hppaelf.sh (TARGET_PAGE_SIZE): Write in hex. + 2000-07-08 Alan Modra * lexsup.c (parse_args): Copy section name. diff --git a/ld/Makefile.am b/ld/Makefile.am index 0569ce021b..1ab671db20 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -104,53 +104,53 @@ ALL_EMULATIONS = \ eaixrs6.o \ ealpha.o \ earcelf.o \ - earmelf.o \ - earmelf_oabi.o \ - earmelf_linux.o \ - earmelf_linux26.o \ + earm_epoc_pe.o \ earmaoutb.o \ earmaoutl.o \ earmcoff.o \ + earmelf.o \ + earmelf_linux.o \ + earmelf_linux26.o \ + earmelf_oabi.o \ earmnbsd.o \ earmpe.o \ - earm_epoc_pe.o \ eavr1200.o \ eavr23xx.o \ - eavr44x4.o \ eavr4433.o \ + eavr44x4.o \ eavr85xx.o \ - eavrmega603.o \ eavrmega103.o \ eavrmega161.o \ + eavrmega603.o \ ecoff_sparc.o \ ed10velf.o \ - ed30velf.o \ ed30v_e.o \ ed30v_o.o \ + ed30velf.o \ edelta68.o \ eebmon29k.o \ - eelf32_sparc.o \ eelf32_i960.o \ + eelf32_sparc.o \ eelf32b4300.o \ eelf32bmip.o \ - eelf32ebmip.o \ - eelf32elmip.o \ eelf32bmipn32.o \ eelf32btsmip.o \ + eelf32ebmip.o \ + eelf32elmip.o \ + eelf32fr30.o \ eelf32i370.o \ eelf32l4300.o \ eelf32lmip.o \ eelf32lppc.o \ eelf32lppcsim.o \ + eelf32mcore.o \ eelf32ppc.o \ - eelf32ppcsim.o \ eelf32ppclinux.o \ + eelf32ppcsim.o \ eelf_i386.o \ eelf_i386_be.o \ egld960.o \ egld960coff.o \ - eelf32fr30.o \ - eelf32mcore.o \ eh8300.o \ eh8300h.o \ eh8300s.o \ @@ -161,6 +161,8 @@ ALL_EMULATIONS = \ eh8500s.o \ ehp300bsd.o \ ehp3hpux.o \ + ehppaelf.o \ + ehppalinux.o \ ei386aout.o \ ei386beos.o \ ei386bsd.o \ @@ -199,10 +201,10 @@ ALL_EMULATIONS = \ emipslnews.o \ emipspe.o \ enews.o \ - epjelf.o \ - epjlelf.o \ ens32knbsd.o \ epc532macha.o \ + epjelf.o \ + epjlelf.o \ eppcmacos.o \ eppcnw.o \ eppcpe.o \ @@ -210,8 +212,8 @@ ALL_EMULATIONS = \ esa29200.o \ esh.o \ eshelf.o \ - eshlelf.o \ eshl.o \ + eshlelf.o \ eshpe.o \ esparcaout.o \ esparclinux.o \ @@ -231,20 +233,16 @@ ALL_EMULATIONS = \ ez8001.o \ ez8002.o -# The following object file has been removed from ALL_EMULATIONS -# because the BFD support is currently broken. -# ehppaelf.o - ALL_64_EMULATIONS = \ eelf64_ia64.o \ eelf64_sparc.o \ eelf64alpha.o \ - eelf64hppa.o \ - eelf64bmip.o + eelf64bmip.o \ + eelf64hppa.o ALL_EMUL_EXTRA_OFILES = \ - pe-dll.o \ - deffilep.o + deffilep.o \ + pe-dll.o CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \ @@ -521,6 +519,9 @@ ehp3hpux.c: $(srcdir)/emulparams/hp3hpux.sh \ ehppaelf.c: $(srcdir)/emulparams/hppaelf.sh \ $(srcdir)/emultempl/hppaelf.em $(srcdir)/scripttempl/hppaelf.sc ${GEN_DEPENDS} ${GENSCRIPTS} hppaelf "$(tdir_hppaelf)" +ehppalinux.c: $(srcdir)/emulparams/hppalinux.sh \ + $(srcdir)/emultempl/hppaelf.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} hppalinux "$(tdir_hppalinux)" ei386aout.c: $(srcdir)/emulparams/i386aout.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} ${GENSCRIPTS} i386aout "$(tdir_i386aout)" diff --git a/ld/Makefile.in b/ld/Makefile.in index be21dcd9b5..20693ad817 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -207,53 +207,53 @@ ALL_EMULATIONS = \ eaixrs6.o \ ealpha.o \ earcelf.o \ - earmelf.o \ - earmelf_oabi.o \ - earmelf_linux.o \ - earmelf_linux26.o \ + earm_epoc_pe.o \ earmaoutb.o \ earmaoutl.o \ earmcoff.o \ + earmelf.o \ + earmelf_linux.o \ + earmelf_linux26.o \ + earmelf_oabi.o \ earmnbsd.o \ earmpe.o \ - earm_epoc_pe.o \ eavr1200.o \ eavr23xx.o \ - eavr44x4.o \ eavr4433.o \ + eavr44x4.o \ eavr85xx.o \ - eavrmega603.o \ eavrmega103.o \ eavrmega161.o \ + eavrmega603.o \ ecoff_sparc.o \ ed10velf.o \ - ed30velf.o \ ed30v_e.o \ ed30v_o.o \ + ed30velf.o \ edelta68.o \ eebmon29k.o \ - eelf32_sparc.o \ eelf32_i960.o \ + eelf32_sparc.o \ eelf32b4300.o \ eelf32bmip.o \ - eelf32ebmip.o \ - eelf32elmip.o \ eelf32bmipn32.o \ eelf32btsmip.o \ + eelf32ebmip.o \ + eelf32elmip.o \ + eelf32fr30.o \ eelf32i370.o \ eelf32l4300.o \ eelf32lmip.o \ eelf32lppc.o \ eelf32lppcsim.o \ + eelf32mcore.o \ eelf32ppc.o \ - eelf32ppcsim.o \ eelf32ppclinux.o \ + eelf32ppcsim.o \ eelf_i386.o \ eelf_i386_be.o \ egld960.o \ egld960coff.o \ - eelf32fr30.o \ - eelf32mcore.o \ eh8300.o \ eh8300h.o \ eh8300s.o \ @@ -264,6 +264,8 @@ ALL_EMULATIONS = \ eh8500s.o \ ehp300bsd.o \ ehp3hpux.o \ + ehppaelf.o \ + ehppalinux.o \ ei386aout.o \ ei386beos.o \ ei386bsd.o \ @@ -302,10 +304,10 @@ ALL_EMULATIONS = \ emipslnews.o \ emipspe.o \ enews.o \ - epjelf.o \ - epjlelf.o \ ens32knbsd.o \ epc532macha.o \ + epjelf.o \ + epjlelf.o \ eppcmacos.o \ eppcnw.o \ eppcpe.o \ @@ -313,8 +315,8 @@ ALL_EMULATIONS = \ esa29200.o \ esh.o \ eshelf.o \ - eshlelf.o \ eshl.o \ + eshlelf.o \ eshpe.o \ esparcaout.o \ esparclinux.o \ @@ -335,21 +337,17 @@ ALL_EMULATIONS = \ ez8002.o -# The following object file has been removed from ALL_EMULATIONS -# because the BFD support is currently broken. -# ehppaelf.o - ALL_64_EMULATIONS = \ eelf64_ia64.o \ eelf64_sparc.o \ eelf64alpha.o \ - eelf64hppa.o \ - eelf64bmip.o + eelf64bmip.o \ + eelf64hppa.o ALL_EMUL_EXTRA_OFILES = \ - pe-dll.o \ - deffilep.o + deffilep.o \ + pe-dll.o CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ @@ -446,7 +444,7 @@ deffilep.c ldgram.c ldlex.c DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) -TAR = gtar +TAR = tar GZIP_ENV = --best SOURCES = $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES) OBJECTS = $(ld_new_OBJECTS) @@ -1222,6 +1220,9 @@ ehp3hpux.c: $(srcdir)/emulparams/hp3hpux.sh \ ehppaelf.c: $(srcdir)/emulparams/hppaelf.sh \ $(srcdir)/emultempl/hppaelf.em $(srcdir)/scripttempl/hppaelf.sc ${GEN_DEPENDS} ${GENSCRIPTS} hppaelf "$(tdir_hppaelf)" +ehppalinux.c: $(srcdir)/emulparams/hppalinux.sh \ + $(srcdir)/emultempl/hppaelf.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} hppalinux "$(tdir_hppalinux)" ei386aout.c: $(srcdir)/emulparams/i386aout.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} ${GENSCRIPTS} i386aout "$(tdir_i386aout)" diff --git a/ld/configure.tgt b/ld/configure.tgt index 8d3c4f05b5..9f257fd815 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -208,6 +208,7 @@ m68*-*-netbsd*) targ_emul=m68knbsd ;; m68*-*-psos*) targ_emul=m68kpsos ;; m68*-*-rtems*) targ_emul=m68kcoff ;; hppa*64*-*) targ_emul=elf64hppa ;; +hppa*-*-linux-gnu*) targ_emul=hppalinux ;; hppa*-*-*elf*) targ_emul=hppaelf ;; hppa*-*-linux-gnu*) targ_emul=hppaelf ;; hppa*-*-lites*) targ_emul=hppaelf ;; diff --git a/ld/emulparams/hppaelf.sh b/ld/emulparams/hppaelf.sh index 47b89ea92a..2cd06ac652 100644 --- a/ld/emulparams/hppaelf.sh +++ b/ld/emulparams/hppaelf.sh @@ -1,7 +1,7 @@ SCRIPT_NAME=hppaelf OUTPUT_FORMAT="elf32-hppa" TEXT_START_ADDR=0x1000 -TARGET_PAGE_SIZE=4096 +TARGET_PAGE_SIZE=0x1000 ARCH=hppa START="$START$" TEMPLATE_NAME=hppaelf diff --git a/ld/emulparams/hppalinux.sh b/ld/emulparams/hppalinux.sh new file mode 100644 index 0000000000..e82315f53a --- /dev/null +++ b/ld/emulparams/hppalinux.sh @@ -0,0 +1,10 @@ +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-hppa" +TEXT_START_ADDR=0x1000 +TARGET_PAGE_SIZE=0x1000 +MAXPAGESIZE=0x1000 +ARCH=hppa +NOP=0x08000240 +START="_start" +TEMPLATE_NAME=hppaelf +DATA_START_SYMBOLS='$global$ = .;' diff --git a/ld/emultempl/hppaelf.em b/ld/emultempl/hppaelf.em index fde4362800..51f3bbd624 100644 --- a/ld/emultempl/hppaelf.em +++ b/ld/emultempl/hppaelf.em @@ -1,8 +1,11 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. cat >e${EMULATION_NAME}.c < #include "bfdlink.h" #include "ld.h" +#include "ldmain.h" #include "ldemul.h" #include "ldfile.h" +#include "ldmisc.h" #include "ldexp.h" #include "ldlang.h" -#include "ldmisc.h" -#include "ldmain.h" +#include "ldgram.h" #include "ldctor.h" +#include "elf32-hppa.h" -/* Section in which we build stubs. */ -static asection *stub_sec; -static lang_input_statement_type *stub_file; +static void hppaelf_before_parse PARAMS ((void)); +static void hppaelf_set_output_arch PARAMS ((void)); +static void hppaelf_create_output_section_statements PARAMS ((void)); +static void hppaelf_delete_padding_statements + PARAMS ((lang_statement_list_type *list)); +static void hppaelf_finish PARAMS ((void)); +static boolean gld${EMULATION_NAME}_place_orphan + PARAMS ((lang_input_statement_type *, asection *)); +static lang_output_section_statement_type *output_rel_find PARAMS ((void)); +static char *hppaelf_get_script PARAMS ((int *)); -/* FIXME. This doesn't belong here. */ -extern lang_statement_list_type file_chain; +/* Fake input file for stubs. */ +static lang_input_statement_type *stub_file; /* Perform some emulation specific initialization. For PA ELF we set up the local label prefix and the output architecture. */ @@ -62,7 +75,7 @@ hppaelf_set_output_arch() } /* This is called before the input files are opened. We create a new - fake input file to hold the stub section. */ + fake input file to hold the stub sections. */ static void hppaelf_create_output_section_statements () @@ -80,66 +93,46 @@ hppaelf_create_output_section_statements () return; } - stub_sec = bfd_make_section_old_way (stub_file->the_bfd, ".text"); - /* Don't set SEC_RELOC until we actually have relocations in this - section. */ - if (stub_sec == NULL - || ! bfd_set_section_flags (stub_file->the_bfd, stub_sec, - (SEC_HAS_CONTENTS - | SEC_ALLOC - | SEC_LOAD - | SEC_CODE - | SEC_IN_MEMORY))) - { - einfo ("%X%P: can not create stub section: %E\n"); - return; - } - ldlang_add_file (stub_file); } -/* Walk all the lang statements splicing out any padding statements from +/* Walk all the lang statements splicing out any padding statements from the list. */ static void -hppaelf_delete_padding_statements (s, prev) - lang_statement_union_type *s; - lang_statement_union_type **prev; +hppaelf_delete_padding_statements (list) + lang_statement_list_type *list; { - lang_statement_union_type *sprev = NULL; - for (; s != NULL; s = s->next) + lang_statement_union_type *s; + lang_statement_union_type **ps; + for (ps = &list->head; (s = *ps) != NULL; ps = &s->next) { switch (s->header.type) { - /* We want recursively walk these sections. */ + /* We want to recursively walk these sections. */ case lang_constructors_statement_enum: - hppaelf_delete_padding_statements (constructor_list.head, - &constructor_list.head); + hppaelf_delete_padding_statements (&constructor_list); break; case lang_output_section_statement_enum: - hppaelf_delete_padding_statements (s->output_section_statement. - children.head, - &s->output_section_statement. - children.head); + hppaelf_delete_padding_statements (&s->output_section_statement.children); + break; + + case lang_group_statement_enum: + hppaelf_delete_padding_statements (&s->group_statement.children); break; - /* Huh? What is a lang_wild_statement? */ case lang_wild_statement_enum: - hppaelf_delete_padding_statements (s->wild_statement. - children.head, - &s->wild_statement. - children.head); + hppaelf_delete_padding_statements (&s->wild_statement.children); break; /* Here's what we are really looking for. Splice these out of the list. */ case lang_padding_statement_enum: - if (sprev) - sprev->header.next = s->header.next; - else - **prev = *s; + *ps = s->next; + if (*ps == NULL) + list->tail = ps; break; /* We don't care about these cases. */ @@ -157,51 +150,435 @@ hppaelf_delete_padding_statements (s, prev) abort (); break; } - sprev = s; } } + +struct hook_stub_info +{ + lang_statement_list_type add; + asection *input_section; +}; + +/* Traverse the linker tree to find the spot where the stub goes. */ + +static boolean +hook_in_stub (info, lp) + struct hook_stub_info *info; + lang_statement_union_type **lp; +{ + lang_statement_union_type *l; + boolean ret; + + for (; (l = *lp) != NULL; lp = &l->next) + { + switch (l->header.type) + { + case lang_constructors_statement_enum: + ret = hook_in_stub (info, &constructor_list.head); + if (ret) + return ret; + break; + + case lang_output_section_statement_enum: + ret = hook_in_stub (info, + &l->output_section_statement.children.head); + if (ret) + return ret; + break; + + case lang_wild_statement_enum: + ret = hook_in_stub (info, &l->wild_statement.children.head); + if (ret) + return ret; + break; + + case lang_group_statement_enum: + ret = hook_in_stub (info, &l->group_statement.children.head); + if (ret) + return ret; + break; + + case lang_input_section_enum: + if (l->input_section.section == info->input_section) + { + /* We've found our section. Insert the stub immediately + before its associated input section. */ + *lp = info->add.head; + *(info->add.tail) = l; + return true; + } + break; + + case lang_data_statement_enum: + case lang_reloc_statement_enum: + case lang_object_symbols_statement_enum: + case lang_output_statement_enum: + case lang_target_statement_enum: + case lang_input_statement_enum: + case lang_assignment_statement_enum: + case lang_padding_statement_enum: + case lang_address_statement_enum: + case lang_fill_statement_enum: + break; + + default: + FAIL (); + break; + } + } + return false; +} + +/* Call-back for elf32_hppa_size_stubs. */ + +/* Create a new stub section, and arrange for it to be linked + immediately before INPUT_SECTION. */ + +static asection * +hppaelf_add_stub_section (stub_name, input_section) + const char *stub_name; + asection *input_section; +{ + asection *stub_sec; + flagword flags; + asection *output_section; + const char *secname; + lang_output_section_statement_type *os; + struct hook_stub_info info; + + stub_sec = bfd_make_section_anyway (stub_file->the_bfd, stub_name); + if (stub_sec == NULL) + goto err_ret; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE + | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP); + if (!bfd_set_section_flags (stub_file->the_bfd, stub_sec, flags)) + goto err_ret; + + output_section = input_section->output_section; + secname = bfd_get_section_name (output_section->owner, output_section); + os = lang_output_section_find (secname); + + info.input_section = input_section; + lang_list_init (&info.add); + wild_doit (&info.add, stub_sec, os, stub_file); + + if (info.add.head == NULL) + goto err_ret; + + if (hook_in_stub (&info, &os->children.head)) + return stub_sec; + + err_ret: + einfo ("%X%P: can not make stub section: %E\n"); + return NULL; +} + +/* Another call-back for elf32_hppa_size_stubs. */ + +static void +hppaelf_layaout_sections_again () +{ + /* If we have changed sizes of the stub sections, then we need + to recalculate all the section offsets. This may mean we need to + add even more stubs. */ + + /* Delete all the padding statements, they're no longer valid. */ + hppaelf_delete_padding_statements (stat_ptr); + + /* Resize the sections. */ + lang_size_sections (stat_ptr->head, abs_output_section, + &stat_ptr->head, 0, (bfd_vma) 0, false); + + /* Redo special stuff. */ + ldemul_after_allocation (); + + /* Do the assignments again. */ + lang_do_assignments (stat_ptr->head, abs_output_section, + (fill_type) 0, (bfd_vma) 0); +} + + /* Final emulation specific call. For the PA we use this opportunity to build linker stubs. */ static void hppaelf_finish () { + /* If generating a relocateable output file, then we don't + have to examine the relocs. */ + if (link_info.relocateable) + return; + /* Call into the BFD backend to do the real work. */ - if (elf32_hppa_size_stubs (stub_file->the_bfd, output_bfd, &link_info) - == false) + if (elf32_hppa_size_stubs (stub_file->the_bfd, + &link_info, + &hppaelf_add_stub_section, + &hppaelf_layaout_sections_again) == false) { einfo ("%X%P: can not size stub section: %E\n"); return; } - - /* If the size of the stub section is nonzero, then we need - to resize the sections, recompute the assignments, and finally - build the stubs. */ - if (bfd_section_size (stub_file->the_bfd, stub_file->the_bfd->sections) != 0) + + /* Now build the linker stubs. */ + if (stub_file->the_bfd->sections != NULL) { - /* Delete all the padding statements, they're no longer valid. */ - hppaelf_delete_padding_statements (stat_ptr->head, &stat_ptr->head); - - /* Resize the sections. */ - lang_size_sections (stat_ptr->head, abs_output_section, - &stat_ptr->head, 0, (bfd_vma) 0, false); - - /* Redo special stuff. */ - ldemul_after_allocation (); - - /* Do the assignments again. */ - lang_do_assignments (stat_ptr->head, - abs_output_section, - (fill_type) 0, (bfd_vma) 0); - - /* Now build the linker stubs. */ if (elf32_hppa_build_stubs (stub_file->the_bfd, &link_info) == false) + einfo ("%X%P: can not build stubs: %E\n"); + } +} + + +/* Place an orphan section. We use this to put random SHF_ALLOC + sections in the right segment. */ + +struct orphan_save +{ + lang_output_section_statement_type *os; + asection **section; + lang_statement_union_type **stmt; +}; + +/*ARGSUSED*/ +static boolean +gld${EMULATION_NAME}_place_orphan (file, s) + lang_input_statement_type *file; + asection *s; +{ + static struct orphan_save hold_text; + static struct orphan_save hold_rodata; + static struct orphan_save hold_data; + static struct orphan_save hold_bss; + static struct orphan_save hold_rel; + static struct orphan_save hold_interp; + struct orphan_save *place; + lang_statement_list_type *old; + lang_statement_list_type add; + etree_type *address; + const char *secname, *ps; + const char *outsecname; + lang_output_section_statement_type *os; + + secname = bfd_get_section_name (s->owner, s); + + /* Look through the script to see where to place this section. */ + os = lang_output_section_find (secname); + + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) + { + /* We have already placed a section with this name. */ + wild_doit (&os->children, s, os, file); + return true; + } + + if (hold_text.os == NULL) + hold_text.os = lang_output_section_find (".text"); + + /* If this is a final link, then always put .gnu.warning.SYMBOL + sections into the .text section to get them out of the way. */ + if (! link_info.shared + && ! link_info.relocateable + && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 + && hold_text.os != NULL) + { + wild_doit (&hold_text.os->children, s, hold_text.os, file); + return true; + } + + /* Decide which segment the section should go in based on the + section name and section flags. We put loadable .note sections + right after the .interp section, so that the PT_NOTE segment is + stored right after the program headers where the OS can read it + in the first page. */ +#define HAVE_SECTION(hold, name) \ +(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) + + if (s->flags & SEC_EXCLUDE) + return false; + else if ((s->flags & SEC_ALLOC) == 0) + place = NULL; + else if ((s->flags & SEC_LOAD) != 0 + && strncmp (secname, ".note", 4) == 0 + && HAVE_SECTION (hold_interp, ".interp")) + place = &hold_interp; + else if ((s->flags & SEC_HAS_CONTENTS) == 0 + && HAVE_SECTION (hold_bss, ".bss")) + place = &hold_bss; + else if ((s->flags & SEC_READONLY) == 0 + && HAVE_SECTION (hold_data, ".data")) + place = &hold_data; + else if (strncmp (secname, ".rel", 4) == 0 + && (hold_rel.os != NULL + || (hold_rel.os = output_rel_find ()) != NULL)) + place = &hold_rel; + else if ((s->flags & SEC_CODE) == 0 + && (s->flags & SEC_READONLY) != 0 + && HAVE_SECTION (hold_rodata, ".rodata")) + place = &hold_rodata; + else if ((s->flags & SEC_READONLY) != 0 + && hold_text.os != NULL) + place = &hold_text; + else + place = NULL; + +#undef HAVE_SECTION + + /* Choose a unique name for the section. This will be needed if the + same section name appears in the input file with different + loadable or allocateable characteristics. */ + outsecname = secname; + if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) + { + unsigned int len; + char *newname; + unsigned int i; + + len = strlen (outsecname); + newname = xmalloc (len + 5); + strcpy (newname, outsecname); + i = 0; + do + { + sprintf (newname + len, "%d", i); + ++i; + } + while (bfd_get_section_by_name (output_bfd, newname) != NULL); + + outsecname = newname; + } + + if (place != NULL) + { + /* Start building a list of statements for this section. */ + old = stat_ptr; + stat_ptr = &add; + lang_list_init (stat_ptr); + + /* If the name of the section is representable in C, then create + symbols to mark the start and the end of the section. */ + for (ps = outsecname; *ps != '\0'; ps++) + if (! isalnum ((unsigned char) *ps) && *ps != '_') + break; + if (*ps == '\0' && config.build_constructors) { - einfo ("%X%P: can not build stubs: %E\n"); - return; + char *symname; + etree_type *e_align; + + symname = (char *) xmalloc (ps - outsecname + sizeof "__start_"); + sprintf (symname, "__start_%s", outsecname); + e_align = exp_unop (ALIGN_K, + exp_intop ((bfd_vma) 1 << s->alignment_power)); + lang_add_assignment (exp_assop ('=', symname, e_align)); } } + + if (link_info.relocateable || (s->flags & (SEC_LOAD | SEC_ALLOC)) == 0) + address = exp_intop ((bfd_vma) 0); + else + address = NULL; + + os = lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); + + wild_doit (&os->children, s, os, file); + + lang_leave_output_section_statement + ((bfd_vma) 0, "*default*", + (struct lang_output_section_phdr_list *) NULL, "*default*"); + + if (place != NULL) + { + asection *snew, **pps; + + stat_ptr = &add; + + if (*ps == '\0' && config.build_constructors) + { + char *symname; + + symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_"); + sprintf (symname, "__stop_%s", outsecname); + lang_add_assignment (exp_assop ('=', symname, + exp_nameop (NAME, "."))); + } + stat_ptr = old; + + snew = os->bfd_section; + if (place->os->bfd_section != NULL || place->section != NULL) + { + /* Shuffle the section to make the output file look neater. */ + if (place->section == NULL) + { +#if 0 + /* Finding the end of the list is a little tricky. We + make a wild stab at it by comparing section flags. */ + flagword first_flags = place->os->bfd_section->flags; + for (pps = &place->os->bfd_section->next; + *pps != NULL && (*pps)->flags == first_flags; + pps = &(*pps)->next) + ; + place->section = pps; +#else + /* Put orphans after the first section on the list. */ + place->section = &place->os->bfd_section->next; +#endif + } + + /* Unlink the section. */ + for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + ; + *pps = snew->next; + + /* Now tack it on to the "place->os" section list. */ + snew->next = *place->section; + *place->section = snew; + } + place->section = &snew->next; /* Save the end of this list. */ + + if (place->stmt == NULL) + { + /* Put the new statement list right at the head. */ + *add.tail = place->os->header.next; + place->os->header.next = add.head; + } + else + { + /* Put it after the last orphan statement we added. */ + *add.tail = *place->stmt; + *place->stmt = add.head; + } + place->stmt = add.tail; /* Save the end of this list. */ + } + + return true; +} + +/* A variant of lang_output_section_find. */ +static lang_output_section_statement_type * +output_rel_find () +{ + lang_statement_union_type *u; + lang_output_section_statement_type *lookup; + + for (u = lang_output_section_statement.head; + u != (lang_statement_union_type *) NULL; + u = lookup->next) + { + lookup = &u->output_section_statement; + if (strncmp (".rel", lookup->name, 4) == 0 + && lookup->bfd_section != NULL + && (lookup->bfd_section->flags & SEC_ALLOC) != 0) + { + return lookup; + } + } + return (lang_output_section_statement_type *) NULL; } /* The script itself gets inserted here. */ @@ -219,7 +596,7 @@ then sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <> e${EMULATION_NAME} sed $sc ldscripts/${EMULATION_NAME}.xbn >> e${EMULATION_NAME}.c echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c + +if test -n "$GENERATE_SHLIB_SCRIPT" ; then +echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c +fi + echo ' ; else return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.x >> e${EMULATION_NAME}.c echo '; }' >> e${EMULATION_NAME}.c @@ -251,6 +634,8 @@ cat >>e${EMULATION_NAME}.c <>e${EMULATION_NAME}.c <