place_orphan optimisations

This commit is contained in:
Alan Modra 2000-04-25 05:14:16 +00:00
parent 8d82e76a9d
commit aea4bd9d34
6 changed files with 159 additions and 182 deletions

View file

@ -1,3 +1,26 @@
2000-04-25 Alan Modra <alan@linuxcare.com.au>
* 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 <nickc@cygnus.com>
* ld.texinfo (Output Section Data): Add note that section data

View file

@ -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;
/* 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);
secname = bfd_get_section_name (s->owner, s);
if (hold_use != NULL)
/* 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 (&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;
lang_statement_union_type *u;
lang_output_section_statement_type *lookup;
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, ".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. */

View file

@ -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;
/* 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);
secname = bfd_get_section_name (s->owner, s);
if (hold_use != NULL)
/* 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 (&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;
lang_statement_union_type *u;
lang_output_section_statement_type *lookup;
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, ".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 *

View file

@ -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;

View file

@ -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;
}

View file

@ -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,