From aea4bd9d34f1b7454f9f04081569e7fe8371fca7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Tue, 25 Apr 2000 05:14:16 +0000 Subject: [PATCH] place_orphan optimisations --- ld/ChangeLog | 23 +++++++++ ld/emultempl/armelf.em | 108 +++++++++++++++++++---------------------- ld/emultempl/elf32.em | 108 +++++++++++++++++++---------------------- ld/emultempl/pe.em | 90 +++++++++++----------------------- ld/ldlang.c | 5 +- ld/ldlang.h | 3 +- 6 files changed, 157 insertions(+), 180 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 36bd2dbd806..9e8e0e5c18f 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,26 @@ +2000-04-25 Alan Modra + + * emultempl/elf32.em (gld${EMULATION_NAME}_place_section): Delete. + (output_rel_find): New function. + (hold_section, hold_use): Delete. + (hold_text, hold_rodata, hold_data, hold_bss, hold_rel, + hold_interp): Make local to place_orphan. + (gld${EMULATION_NAME}_place_orphan): Use lang_output_section_find + rather than place_section to find possible previous use of orphan. + Similarly find the place-holder output sections. Use returned + value from lang_enter_output_section_statement rather than calling + lang_output_section_statement_lookup. + * emultempl/armelf.em: Same here. + * emultempl/pe.em: Similar to above, but no need for output_rel_find. + + * ldlang.c (lang_enter_output_section_statement): Return output + section statement. + * ldlang.h (lang_enter_output_section_statement): Change + declaration too. + + * ldlang.h (lang_output_section_statement): Export it. + * ldlang.c (lang_output_section_statement): Ditto. + 2000-04-24 Nick Clifton * ld.texinfo (Output Section Data): Add note that section data diff --git a/ld/emultempl/armelf.em b/ld/emultempl/armelf.em index 8de6c9bc3e0..a1a39683107 100644 --- a/ld/emultempl/armelf.em +++ b/ld/emultempl/armelf.em @@ -61,8 +61,7 @@ static void gld${EMULATION_NAME}_find_statement_assignment static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); static boolean gld${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); -static void gld${EMULATION_NAME}_place_section - PARAMS ((lang_statement_union_type *)); +static lang_output_section_statement_type *output_rel_find PARAMS ((void)); static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); @@ -783,21 +782,12 @@ gld${EMULATION_NAME}_vercheck (s) /* Place an orphan section. We use this to put random SHF_ALLOC sections in the right segment. */ -static asection *hold_section; -static lang_output_section_statement_type *hold_use; - struct orphan_save { lang_output_section_statement_type *os; asection **section; lang_statement_union_type **stmt; }; -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; /*ARGSUSED*/ static boolean @@ -805,6 +795,12 @@ 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; @@ -813,19 +809,22 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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. */ - hold_section = s; - hold_use = NULL; - lang_for_each_statement (gld${EMULATION_NAME}_place_section); + os = lang_output_section_find (secname); - if (hold_use != NULL) + 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 (&hold_use->children, s, hold_use, file); + wild_doit (&os->children, s, os, file); return true; } - secname = bfd_get_section_name (s->owner, s); + 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. */ @@ -843,26 +842,30 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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 - && hold_interp.os != NULL) + && HAVE_SECTION (hold_interp, ".interp")) place = &hold_interp; else if ((s->flags & SEC_HAS_CONTENTS) == 0 - && hold_bss.os != NULL) + && HAVE_SECTION (hold_bss, ".bss")) place = &hold_bss; else if ((s->flags & SEC_READONLY) == 0 - && hold_data.os != NULL) + && HAVE_SECTION (hold_data, ".data")) place = &hold_data; else if (strncmp (secname, ".rel", 4) == 0 - && hold_rel.os != NULL) + && (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 - && hold_rodata.os != NULL) + && HAVE_SECTION (hold_rodata, ".rodata")) place = &hold_rodata; else if ((s->flags & SEC_READONLY) != 0 && hold_text.os != NULL) @@ -870,6 +873,8 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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. */ @@ -924,13 +929,12 @@ gld${EMULATION_NAME}_place_orphan (file, s) else address = NULL; - lang_enter_output_section_statement (outsecname, address, 0, - (bfd_vma) 0, - (etree_type *) NULL, - (etree_type *) NULL, - (etree_type *) NULL); + os = lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); - os = lang_output_section_statement_lookup (outsecname); wild_doit (&os->children, s, os, file); lang_leave_output_section_statement @@ -1004,38 +1008,26 @@ gld${EMULATION_NAME}_place_orphan (file, s) return true; } -static void -gld${EMULATION_NAME}_place_section (s) - lang_statement_union_type *s; +/* A variant of lang_output_section_find. */ +static lang_output_section_statement_type * +output_rel_find () { - lang_output_section_statement_type *os; - - if (s->header.type != lang_output_section_statement_enum) - return; + lang_statement_union_type *u; + lang_output_section_statement_type *lookup; - os = &s->output_section_statement; - - if (strcmp (os->name, hold_section->name) == 0 - && os->bfd_section != NULL - && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) - == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) - hold_use = os; - - if (strcmp (os->name, ".text") == 0) - hold_text.os = os; - else if (strcmp (os->name, ".rodata") == 0) - hold_rodata.os = os; - else if (strcmp (os->name, ".data") == 0) - hold_data.os = os; - else if (strcmp (os->name, ".bss") == 0) - hold_bss.os = os; - else if (hold_rel.os == NULL - && os->bfd_section != NULL - && (os->bfd_section->flags & SEC_ALLOC) != 0 - && strncmp (os->name, ".rel", 4) == 0) - hold_rel.os = os; - else if (strcmp (os->name, ".interp") == 0) - hold_interp.os = os; + 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; } /* Look through an expression for an assignment statement. */ diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index d57aadb1a7e..96152850027 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -65,8 +65,7 @@ static void gld${EMULATION_NAME}_find_statement_assignment static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); static boolean gld${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); -static void gld${EMULATION_NAME}_place_section - PARAMS ((lang_statement_union_type *)); +static lang_output_section_statement_type *output_rel_find PARAMS ((void)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); static void @@ -865,21 +864,12 @@ gld${EMULATION_NAME}_find_exp_assignment (exp) /* Place an orphan section. We use this to put random SHF_ALLOC sections in the right segment. */ -static asection *hold_section; -static lang_output_section_statement_type *hold_use; - struct orphan_save { lang_output_section_statement_type *os; asection **section; lang_statement_union_type **stmt; }; -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; /*ARGSUSED*/ static boolean @@ -887,6 +877,12 @@ 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; @@ -895,19 +891,22 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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. */ - hold_section = s; - hold_use = NULL; - lang_for_each_statement (gld${EMULATION_NAME}_place_section); + os = lang_output_section_find (secname); - if (hold_use != NULL) + 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 (&hold_use->children, s, hold_use, file); + wild_doit (&os->children, s, os, file); return true; } - secname = bfd_get_section_name (s->owner, s); + 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. */ @@ -925,26 +924,30 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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 - && hold_interp.os != NULL) + && HAVE_SECTION (hold_interp, ".interp")) place = &hold_interp; else if ((s->flags & SEC_HAS_CONTENTS) == 0 - && hold_bss.os != NULL) + && HAVE_SECTION (hold_bss, ".bss")) place = &hold_bss; else if ((s->flags & SEC_READONLY) == 0 - && hold_data.os != NULL) + && HAVE_SECTION (hold_data, ".data")) place = &hold_data; else if (strncmp (secname, ".rel", 4) == 0 - && hold_rel.os != NULL) + && (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 - && hold_rodata.os != NULL) + && HAVE_SECTION (hold_rodata, ".rodata")) place = &hold_rodata; else if ((s->flags & SEC_READONLY) != 0 && hold_text.os != NULL) @@ -952,6 +955,8 @@ gld${EMULATION_NAME}_place_orphan (file, s) 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. */ @@ -1006,13 +1011,12 @@ gld${EMULATION_NAME}_place_orphan (file, s) else address = NULL; - lang_enter_output_section_statement (outsecname, address, 0, - (bfd_vma) 0, - (etree_type *) NULL, - (etree_type *) NULL, - (etree_type *) NULL); + os = lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); - os = lang_output_section_statement_lookup (outsecname); wild_doit (&os->children, s, os, file); lang_leave_output_section_statement @@ -1086,38 +1090,26 @@ gld${EMULATION_NAME}_place_orphan (file, s) return true; } -static void -gld${EMULATION_NAME}_place_section (s) - lang_statement_union_type *s; +/* A variant of lang_output_section_find. */ +static lang_output_section_statement_type * +output_rel_find () { - lang_output_section_statement_type *os; - - if (s->header.type != lang_output_section_statement_enum) - return; + lang_statement_union_type *u; + lang_output_section_statement_type *lookup; - os = &s->output_section_statement; - - if (strcmp (os->name, hold_section->name) == 0 - && os->bfd_section != NULL - && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) - == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) - hold_use = os; - - if (strcmp (os->name, ".text") == 0) - hold_text.os = os; - else if (strcmp (os->name, ".rodata") == 0) - hold_rodata.os = os; - else if (strcmp (os->name, ".data") == 0) - hold_data.os = os; - else if (strcmp (os->name, ".bss") == 0) - hold_bss.os = os; - else if (hold_rel.os == NULL - && os->bfd_section != NULL - && (os->bfd_section->flags & SEC_ALLOC) != 0 - && strncmp (os->name, ".rel", 4) == 0) - hold_rel.os = os; - else if (strcmp (os->name, ".interp") == 0) - hold_interp.os = os; + 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; } static char * diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index aeecb614109..06ae8687235 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -102,8 +102,6 @@ static void gld_${EMULATION_NAME}_after_parse PARAMS ((void)); static void gld_${EMULATION_NAME}_before_allocation PARAMS ((void)); static boolean gld_${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); -static void gld${EMULATION_NAME}_place_section - PARAMS ((lang_statement_union_type *)); static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *)); static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); static void gld_${EMULATION_NAME}_finish PARAMS ((void)); @@ -1074,23 +1072,12 @@ gld_${EMULATION_NAME}_finish () default linker script using wildcards, and are sorted by sort_sections. */ -static asection *hold_section; -static char *hold_section_name; -static lang_output_section_statement_type *hold_use; - struct orphan_save { lang_output_section_statement_type *os; asection **section; lang_statement_union_type **stmt; }; -static struct orphan_save hold_text; -static struct orphan_save hold_rdata; -static struct orphan_save hold_data; -static struct orphan_save hold_bss; - -/* Place an orphan section. We use this to put random SHF_ALLOC - sections in the right segment. */ /*ARGSUSED*/ static boolean @@ -1099,15 +1086,15 @@ gld_${EMULATION_NAME}_place_orphan (file, s) asection *s; { const char *secname; + char *hold_section_name; char *dollar = NULL; + lang_output_section_statement_type *os; lang_statement_list_type add_child; secname = bfd_get_section_name (s->owner, s); /* Look through the script to see where to place this section. */ - hold_section = s; - hold_section_name = xstrdup (secname); if (!link_info.relocateable) { @@ -1116,18 +1103,23 @@ gld_${EMULATION_NAME}_place_orphan (file, s) *dollar = '\0'; } - hold_use = NULL; - lang_for_each_statement (gld${EMULATION_NAME}_place_section); + os = lang_output_section_find (hold_section_name); lang_list_init (&add_child); - if (hold_use != NULL) + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) { - wild_doit (&add_child, s, hold_use, file); + wild_doit (&add_child, s, os, file); } else { struct orphan_save *place; + static struct orphan_save hold_text; + static struct orphan_save hold_rdata; + static struct orphan_save hold_data; + static struct orphan_save hold_bss; char *outsecname; lang_statement_list_type *old; lang_statement_list_type add; @@ -1135,23 +1127,28 @@ gld_${EMULATION_NAME}_place_orphan (file, s) /* Try to put the new output section in a reasonable place based on the section name and section flags. */ +#define HAVE_SECTION(hold, name) \ +(hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) + place = NULL; if ((s->flags & SEC_ALLOC) == 0) ; else if ((s->flags & SEC_HAS_CONTENTS) == 0 - && hold_bss.os != NULL) + && HAVE_SECTION (hold_bss, ".bss")) place = &hold_bss; else if ((s->flags & SEC_READONLY) == 0 - && hold_data.os != NULL) + && HAVE_SECTION (hold_data, ".data")) place = &hold_data; else if ((s->flags & SEC_CODE) == 0 && (s->flags & SEC_READONLY) != 0 - && hold_rdata.os != NULL) + && HAVE_SECTION (hold_rdata, ".rdata")) place = &hold_rdata; else if ((s->flags & SEC_READONLY) != 0 - && hold_text.os != NULL) + && HAVE_SECTION (hold_text, ".text")) place = &hold_text; +#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. */ @@ -1192,19 +1189,17 @@ gld_${EMULATION_NAME}_place_orphan (file, s) exp_nameop (NAME, "__section_alignment__")); } - lang_enter_output_section_statement (outsecname, address, 0, - (bfd_vma) 0, - (etree_type *) NULL, - (etree_type *) NULL, - (etree_type *) NULL); + os = lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); - hold_use = lang_output_section_statement_lookup (outsecname); - wild_doit (&add_child, s, hold_use, file); + wild_doit (&add_child, s, os, file); lang_leave_output_section_statement ((bfd_vma) 0, "*default*", - (struct lang_output_section_phdr_list *) NULL, - "*default*"); + (struct lang_output_section_phdr_list *) NULL, "*default*"); stat_ptr = old; @@ -1212,7 +1207,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s) { asection *snew, **pps; - snew = hold_use->bfd_section; + snew = os->bfd_section; if (place->os->bfd_section != NULL || place->section != NULL) { /* Shuffle the section to make the output file look neater. */ @@ -1261,7 +1256,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s) } { - lang_statement_union_type **pl = &hold_use->children.head; + lang_statement_union_type **pl = &os->children.head; if (dollar != NULL) { @@ -1308,33 +1303,6 @@ gld_${EMULATION_NAME}_place_orphan (file, s) return true; } -static void -gld${EMULATION_NAME}_place_section (s) - lang_statement_union_type *s; -{ - lang_output_section_statement_type *os; - - if (s->header.type != lang_output_section_statement_enum) - return; - - os = &s->output_section_statement; - - if (strcmp (os->name, hold_section_name) == 0 - && os->bfd_section != NULL - && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) - == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) - hold_use = os; - - if (strcmp (os->name, ".text") == 0) - hold_text.os = os; - else if (strcmp (os->name, ".rdata") == 0) - hold_rdata.os = os; - else if (strcmp (os->name, ".data") == 0) - hold_data.os = os; - else if (strcmp (os->name, ".bss") == 0) - hold_bss.os = os; -} - static int gld_${EMULATION_NAME}_find_potential_libraries (name, entry) char * name; diff --git a/ld/ldlang.c b/ld/ldlang.c index d40ff07a5b3..8f0c607b7a1 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -58,7 +58,6 @@ static lang_output_section_statement_type *default_common_section; static boolean map_option_f; static bfd_vma print_dot; static lang_input_statement_type *first_file; -static lang_statement_list_type lang_output_section_statement; static CONST char *current_target; static CONST char *output_target; static lang_statement_list_type statement_list; @@ -166,6 +165,7 @@ static char * get_first_input_target PARAMS ((void)); /* EXPORTS */ lang_output_section_statement_type *abs_output_section; +lang_statement_list_type lang_output_section_statement; lang_statement_list_type *stat_ptr = &statement_list; lang_statement_list_type file_chain = { NULL, NULL }; const char *entry_symbol = NULL; @@ -3813,7 +3813,7 @@ topower (x) return 0; } -void +lang_output_section_statement_type * lang_enter_output_section_statement (output_section_statement_name, address_exp, sectype, block_value, align, subalign, ebase) @@ -3861,6 +3861,7 @@ lang_enter_output_section_statement (output_section_statement_name, "section alignment", 0)); os->load_base = ebase; + return os; } diff --git a/ld/ldlang.h b/ld/ldlang.h index 068cd96ac84..553db4b2a05 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -371,6 +371,7 @@ struct lang_nocrossrefs extern struct lang_nocrossrefs *nocrossref_list; extern lang_output_section_statement_type *abs_output_section; +extern lang_statement_list_type lang_output_section_statement; extern boolean lang_has_input_file; extern etree_type *base; extern lang_statement_list_type *stat_ptr; @@ -388,7 +389,7 @@ extern void lang_map PARAMS ((void)); extern void lang_set_flags PARAMS ((lang_memory_region_type *, const char *, int)); extern void lang_add_output PARAMS ((const char *, int from_script)); -extern void lang_enter_output_section_statement +extern lang_output_section_statement_type *lang_enter_output_section_statement PARAMS ((const char *output_section_statement_name, etree_type * address_exp, enum section_type sectype, -- 2.30.2