yann@1: Signed-off-by: dank@kegel.com yann@1: Fixes ld speed issue. yann@1: See http://weblogs.mozillazine.org/roc/archives/2005/02/optimizing_gnu.html yann@1: See thread "Re: optimizations for 3x speedup in ld", yann@1: http://sources.redhat.com/ml/binutils/2005-03/msg00847.html yann@1: yann@1: Wildcard section matching enhancement, backported from the binutils CVS tree. yann@1: Here's the CVS log comment from the original change to ldlang.c: yann@1: yann@1: revision 1.177 yann@1: date: 2005/04/06 15:33:02; author: jakub; state: Exp; lines: +438 -51 yann@1: 2005-04-06 Jakub Jelinek yann@1: yann@1: * ldlang.c: Formatting. yann@1: (walk_wild_consider_section): Remember return value from wildcardp. yann@1: (is_simple_wild): Use strcspn instead of 2 strpbrk calls and strlen. yann@1: (wild_spec_can_overlap): Use strcspn instead of strpbrk and strlen. yann@1: yann@1: 2005-04-06 Robert O'Callahan yann@1: yann@1: * ld.h (lean_section_userdata_type): Remove. yann@1: (fat_section_userdata_type): Remove file field. yann@1: (SECTION_USERDATA_SIZE): Remove. yann@1: * ldlang.c (init_os): Eliminate initialization of unused yann@1: lean_section_userdata_type. yann@1: yann@1: * ldlang.h (callback_t, walk_wild_section_handler_t): New yann@1: typedefs. yann@1: (struct lang_wild_statement_struct): Add walk_wild_section_handler yann@1: and handler_data fields. yann@1: * ldlang.c (callback_t): Removed. yann@1: (walk_wild_consider_section, walk_wild_section_general, yann@1: section_iterator_callback, find_section, is_simple_wild, yann@1: match_simple_wild, walk_wild_section_specs1_wild0, yann@1: walk_wild_section_specs1_wild1, walk_wild_section_specs2_wild1, yann@1: walk_wild_section_specs3_wild2, walk_wild_section_specs4_wild2, yann@1: wild_spec_can_overlap, analyze_walk_wild_section_handler): New yann@1: functions. yann@1: (lang_add_wild): Call analyze_walk_wild_section_handler. yann@1: (walk_wild_section): Renamed to walk_wild_section_general and yann@1: created a wrapper function. yann@1: (section_iterator_callback_data): New typedef. yann@1: yann@1: Note that bfd_get_section_by_name_if didn't exist in 2.15, so it was backported yann@1: as well. yann@1: yann@1: --- binutils-2.15/bfd/bfd-in2.h.old 2004-05-17 15:35:56.000000000 -0400 yann@1: +++ binutils-2.15/bfd/bfd-in2.h 2006-02-09 11:54:45.989940000 -0500 yann@1: @@ -1425,6 +1425,10 @@ yann@1: yann@1: asection *bfd_get_section_by_name (bfd *abfd, const char *name); yann@1: yann@1: +asection *bfd_get_section_by_name_if (bfd *abfd, const char *name, yann@1: + bfd_boolean (*operation) (bfd *, asection *, void *), yann@1: + void *user_storage); yann@1: + yann@1: char *bfd_get_unique_section_name yann@1: (bfd *abfd, const char *templat, int *count); yann@1: yann@1: --- binutils-2.15/bfd/section.c.old 2003-12-01 01:33:01.000000000 -0500 yann@1: +++ binutils-2.15/bfd/section.c 2006-01-23 14:16:54.768993000 -0500 yann@1: @@ -801,6 +801,57 @@ yann@1: yann@1: /* yann@1: FUNCTION yann@1: + bfd_get_section_by_name_if yann@1: + yann@1: +SYNOPSIS yann@1: + asection *bfd_get_section_by_name_if yann@1: + (bfd *abfd, yann@1: + const char *name, yann@1: + bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj), yann@1: + void *obj); yann@1: + yann@1: +DESCRIPTION yann@1: + Call the provided function @var{func} for each section yann@1: + attached to the BFD @var{abfd} whose name matches @var{name}, yann@1: + passing @var{obj} as an argument. The function will be called yann@1: + as if by yann@1: + yann@1: +| func (abfd, the_section, obj); yann@1: + yann@1: + It returns the first section for which @var{func} returns true, yann@1: + otherwise <>. yann@1: + yann@1: +*/ yann@1: + yann@1: +asection * yann@1: +bfd_get_section_by_name_if (bfd *abfd, const char *name, yann@1: + bfd_boolean (*operation) (bfd *, yann@1: + asection *, yann@1: + void *), yann@1: + void *user_storage) yann@1: +{ yann@1: + struct section_hash_entry *sh; yann@1: + unsigned long hash; yann@1: + yann@1: + sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE); yann@1: + if (sh == NULL) yann@1: + return NULL; yann@1: + yann@1: + hash = sh->root.hash; yann@1: + do yann@1: + { yann@1: + if ((*operation) (abfd, &sh->section, user_storage)) yann@1: + return &sh->section; yann@1: + sh = (struct section_hash_entry *) sh->root.next; yann@1: + } yann@1: + while (sh != NULL && sh->root.hash == hash yann@1: + && strcmp (sh->root.string, name) == 0); yann@1: + yann@1: + return NULL; yann@1: +} yann@1: + yann@1: +/* yann@1: +FUNCTION yann@1: bfd_get_unique_section_name yann@1: yann@1: SYNOPSIS yann@1: --- binutils-2.15/ld/ldlang.c.old 2004-05-17 15:36:16.000000000 -0400 yann@1: +++ binutils-2.15/ld/ldlang.c 2006-01-23 13:40:12.745499000 -0500 yann@1: @@ -81,9 +81,6 @@ yann@1: static void lang_record_phdrs (void); yann@1: static void lang_do_version_exports_section (void); yann@1: yann@1: -typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *, yann@1: - asection *, lang_input_statement_type *, void *); yann@1: - yann@1: /* Exported variables. */ yann@1: lang_output_section_statement_type *abs_output_section; yann@1: lang_statement_list_type lang_output_section_statement; yann@1: @@ -138,21 +135,71 @@ yann@1: yann@1: /* Generic traversal routines for finding matching sections. */ yann@1: yann@1: +/* Try processing a section against a wildcard. This just calls yann@1: + the callback unless the filename exclusion list is present yann@1: + and excludes the file. It's hardly ever present so this yann@1: + function is very fast. */ yann@1: + yann@1: +static void yann@1: +walk_wild_consider_section (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + asection *s, yann@1: + struct wildcard_list *sec, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + bfd_boolean skip = FALSE; yann@1: + struct name_list *list_tmp; yann@1: + yann@1: + /* Don't process sections from files which were yann@1: + excluded. */ yann@1: + for (list_tmp = sec->spec.exclude_name_list; yann@1: + list_tmp; yann@1: + list_tmp = list_tmp->next) yann@1: + { yann@1: + bfd_boolean is_wildcard = wildcardp (list_tmp->name); yann@1: + if (is_wildcard) yann@1: + skip = fnmatch (list_tmp->name, file->filename, 0) == 0; yann@1: + else yann@1: + skip = strcmp (list_tmp->name, file->filename) == 0; yann@1: + yann@1: + /* If this file is part of an archive, and the archive is yann@1: + excluded, exclude this file. */ yann@1: + if (! skip && file->the_bfd != NULL yann@1: + && file->the_bfd->my_archive != NULL yann@1: + && file->the_bfd->my_archive->filename != NULL) yann@1: + { yann@1: + if (is_wildcard) yann@1: + skip = fnmatch (list_tmp->name, yann@1: + file->the_bfd->my_archive->filename, yann@1: + 0) == 0; yann@1: + else yann@1: + skip = strcmp (list_tmp->name, yann@1: + file->the_bfd->my_archive->filename) == 0; yann@1: + } yann@1: + yann@1: + if (skip) yann@1: + break; yann@1: + } yann@1: + yann@1: + if (!skip) yann@1: + (*callback) (ptr, sec, s, file, data); yann@1: +} yann@1: + yann@1: +/* Lowest common denominator routine that can handle everything correctly, yann@1: + but slowly. */ yann@1: + yann@1: static void yann@1: -walk_wild_section (lang_wild_statement_type *ptr, yann@1: - lang_input_statement_type *file, yann@1: - callback_t callback, yann@1: - void *data) yann@1: +walk_wild_section_general (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: { yann@1: asection *s; yann@1: - yann@1: - if (file->just_syms_flag) yann@1: - return; yann@1: + struct wildcard_list *sec; yann@1: yann@1: for (s = file->the_bfd->sections; s != NULL; s = s->next) yann@1: { yann@1: - struct wildcard_list *sec; yann@1: - yann@1: sec = ptr->section_list; yann@1: if (sec == NULL) yann@1: (*callback) (ptr, sec, s, file, data); yann@1: @@ -160,39 +207,8 @@ yann@1: while (sec != NULL) yann@1: { yann@1: bfd_boolean skip = FALSE; yann@1: - struct name_list *list_tmp; yann@1: - yann@1: - /* Don't process sections from files which were yann@1: - excluded. */ yann@1: - for (list_tmp = sec->spec.exclude_name_list; yann@1: - list_tmp; yann@1: - list_tmp = list_tmp->next) yann@1: - { yann@1: - if (wildcardp (list_tmp->name)) yann@1: - skip = fnmatch (list_tmp->name, file->filename, 0) == 0; yann@1: - else yann@1: - skip = strcmp (list_tmp->name, file->filename) == 0; yann@1: - yann@1: - /* If this file is part of an archive, and the archive is yann@1: - excluded, exclude this file. */ yann@1: - if (! skip && file->the_bfd != NULL yann@1: - && file->the_bfd->my_archive != NULL yann@1: - && file->the_bfd->my_archive->filename != NULL) yann@1: - { yann@1: - if (wildcardp (list_tmp->name)) yann@1: - skip = fnmatch (list_tmp->name, yann@1: - file->the_bfd->my_archive->filename, yann@1: - 0) == 0; yann@1: - else yann@1: - skip = strcmp (list_tmp->name, yann@1: - file->the_bfd->my_archive->filename) == 0; yann@1: - } yann@1: - yann@1: - if (skip) yann@1: - break; yann@1: - } yann@1: yann@1: - if (!skip && sec->spec.name != NULL) yann@1: + if (sec->spec.name != NULL) yann@1: { yann@1: const char *sname = bfd_get_section_name (file->the_bfd, s); yann@1: yann@1: @@ -203,13 +219,381 @@ yann@1: } yann@1: yann@1: if (!skip) yann@1: - (*callback) (ptr, sec, s, file, data); yann@1: + walk_wild_consider_section (ptr, file, s, sec, callback, data); yann@1: yann@1: sec = sec->next; yann@1: } yann@1: } yann@1: } yann@1: yann@1: +/* Routines to find a single section given its name. If there's more yann@1: + than one section with that name, we report that. */ yann@1: + yann@1: +typedef struct yann@1: +{ yann@1: + asection *found_section; yann@1: + bfd_boolean multiple_sections_found; yann@1: +} section_iterator_callback_data; yann@1: + yann@1: +static bfd_boolean yann@1: +section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data) yann@1: +{ yann@1: + section_iterator_callback_data *d = data; yann@1: + yann@1: + if (d->found_section != NULL) yann@1: + { yann@1: + d->multiple_sections_found = TRUE; yann@1: + return TRUE; yann@1: + } yann@1: + yann@1: + d->found_section = s; yann@1: + return FALSE; yann@1: +} yann@1: + yann@1: +static asection * yann@1: +find_section (lang_input_statement_type *file, yann@1: + struct wildcard_list *sec, yann@1: + bfd_boolean *multiple_sections_found) yann@1: +{ yann@1: + section_iterator_callback_data cb_data = { NULL, FALSE }; yann@1: + yann@1: + bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, yann@1: + section_iterator_callback, &cb_data); yann@1: + *multiple_sections_found = cb_data.multiple_sections_found; yann@1: + return cb_data.found_section; yann@1: +} yann@1: + yann@1: +/* Code for handling simple wildcards without going through fnmatch, yann@1: + which can be expensive because of charset translations etc. */ yann@1: + yann@1: +/* A simple wild is a literal string followed by a single '*', yann@1: + where the literal part is at least 4 characters long. */ yann@1: + yann@1: +static bfd_boolean yann@1: +is_simple_wild (const char *name) yann@1: +{ yann@1: + size_t len = strcspn (name, "*?["); yann@1: + return len >= 4 && name[len] == '*' && name[len + 1] == '\0'; yann@1: +} yann@1: + yann@1: +static bfd_boolean yann@1: +match_simple_wild (const char *pattern, const char *name) yann@1: +{ yann@1: + /* The first four characters of the pattern are guaranteed valid yann@1: + non-wildcard characters. So we can go faster. */ yann@1: + if (pattern[0] != name[0] || pattern[1] != name[1] yann@1: + || pattern[2] != name[2] || pattern[3] != name[3]) yann@1: + return FALSE; yann@1: + yann@1: + pattern += 4; yann@1: + name += 4; yann@1: + while (*pattern != '*') yann@1: + if (*name++ != *pattern++) yann@1: + return FALSE; yann@1: + yann@1: + return TRUE; yann@1: +} yann@1: + yann@1: +/* Specialized, optimized routines for handling different kinds of yann@1: + wildcards */ yann@1: + yann@1: +static void yann@1: +walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + /* We can just do a hash lookup for the section with the right name. yann@1: + But if that lookup discovers more than one section with the name yann@1: + (should be rare), we fall back to the general algorithm because yann@1: + we would otherwise have to sort the sections to make sure they yann@1: + get processed in the bfd's order. */ yann@1: + bfd_boolean multiple_sections_found; yann@1: + struct wildcard_list *sec0 = ptr->handler_data[0]; yann@1: + asection *s0 = find_section (file, sec0, &multiple_sections_found); yann@1: + yann@1: + if (multiple_sections_found) yann@1: + walk_wild_section_general (ptr, file, callback, data); yann@1: + else if (s0) yann@1: + walk_wild_consider_section (ptr, file, s0, sec0, callback, data); yann@1: +} yann@1: + yann@1: +static void yann@1: +walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + asection *s; yann@1: + struct wildcard_list *wildsec0 = ptr->handler_data[0]; yann@1: + yann@1: + for (s = file->the_bfd->sections; s != NULL; s = s->next) yann@1: + { yann@1: + const char *sname = bfd_get_section_name (file->the_bfd, s); yann@1: + bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname); yann@1: + yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec0, callback, data); yann@1: + } yann@1: +} yann@1: + yann@1: +static void yann@1: +walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + asection *s; yann@1: + struct wildcard_list *sec0 = ptr->handler_data[0]; yann@1: + struct wildcard_list *wildsec1 = ptr->handler_data[1]; yann@1: + bfd_boolean multiple_sections_found; yann@1: + asection *s0 = find_section (file, sec0, &multiple_sections_found); yann@1: + yann@1: + if (multiple_sections_found) yann@1: + { yann@1: + walk_wild_section_general (ptr, file, callback, data); yann@1: + return; yann@1: + } yann@1: + yann@1: + /* Note that if the section was not found, s0 is NULL and yann@1: + we'll simply never succeed the s == s0 test below. */ yann@1: + for (s = file->the_bfd->sections; s != NULL; s = s->next) yann@1: + { yann@1: + /* Recall that in this code path, a section cannot satisfy more yann@1: + than one spec, so if s == s0 then it cannot match yann@1: + wildspec1. */ yann@1: + if (s == s0) yann@1: + walk_wild_consider_section (ptr, file, s, sec0, callback, data); yann@1: + else yann@1: + { yann@1: + const char *sname = bfd_get_section_name (file->the_bfd, s); yann@1: + bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); yann@1: + yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec1, callback, yann@1: + data); yann@1: + } yann@1: + } yann@1: +} yann@1: + yann@1: +static void yann@1: +walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + asection *s; yann@1: + struct wildcard_list *sec0 = ptr->handler_data[0]; yann@1: + struct wildcard_list *wildsec1 = ptr->handler_data[1]; yann@1: + struct wildcard_list *wildsec2 = ptr->handler_data[2]; yann@1: + bfd_boolean multiple_sections_found; yann@1: + asection *s0 = find_section (file, sec0, &multiple_sections_found); yann@1: + yann@1: + if (multiple_sections_found) yann@1: + { yann@1: + walk_wild_section_general (ptr, file, callback, data); yann@1: + return; yann@1: + } yann@1: + yann@1: + for (s = file->the_bfd->sections; s != NULL; s = s->next) yann@1: + { yann@1: + if (s == s0) yann@1: + walk_wild_consider_section (ptr, file, s, sec0, callback, data); yann@1: + else yann@1: + { yann@1: + const char *sname = bfd_get_section_name (file->the_bfd, s); yann@1: + bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname); yann@1: + yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec1, callback, data); yann@1: + else yann@1: + { yann@1: + skip = !match_simple_wild (wildsec2->spec.name, sname); yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec2, callback, yann@1: + data); yann@1: + } yann@1: + } yann@1: + } yann@1: +} yann@1: + yann@1: +static void yann@1: +walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + asection *s; yann@1: + struct wildcard_list *sec0 = ptr->handler_data[0]; yann@1: + struct wildcard_list *sec1 = ptr->handler_data[1]; yann@1: + struct wildcard_list *wildsec2 = ptr->handler_data[2]; yann@1: + struct wildcard_list *wildsec3 = ptr->handler_data[3]; yann@1: + bfd_boolean multiple_sections_found; yann@1: + asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1; yann@1: + yann@1: + if (multiple_sections_found) yann@1: + { yann@1: + walk_wild_section_general (ptr, file, callback, data); yann@1: + return; yann@1: + } yann@1: + yann@1: + s1 = find_section (file, sec1, &multiple_sections_found); yann@1: + if (multiple_sections_found) yann@1: + { yann@1: + walk_wild_section_general (ptr, file, callback, data); yann@1: + return; yann@1: + } yann@1: + yann@1: + for (s = file->the_bfd->sections; s != NULL; s = s->next) yann@1: + { yann@1: + if (s == s0) yann@1: + walk_wild_consider_section (ptr, file, s, sec0, callback, data); yann@1: + else yann@1: + if (s == s1) yann@1: + walk_wild_consider_section (ptr, file, s, sec1, callback, data); yann@1: + else yann@1: + { yann@1: + const char *sname = bfd_get_section_name (file->the_bfd, s); yann@1: + bfd_boolean skip = !match_simple_wild (wildsec2->spec.name, yann@1: + sname); yann@1: + yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec2, callback, yann@1: + data); yann@1: + else yann@1: + { yann@1: + skip = !match_simple_wild (wildsec3->spec.name, sname); yann@1: + if (!skip) yann@1: + walk_wild_consider_section (ptr, file, s, wildsec3, yann@1: + callback, data); yann@1: + } yann@1: + } yann@1: + } yann@1: +} yann@1: + yann@1: +static void yann@1: +walk_wild_section (lang_wild_statement_type *ptr, yann@1: + lang_input_statement_type *file, yann@1: + callback_t callback, yann@1: + void *data) yann@1: +{ yann@1: + if (file->just_syms_flag) yann@1: + return; yann@1: + yann@1: + (*ptr->walk_wild_section_handler) (ptr, file, callback, data); yann@1: +} yann@1: + yann@1: +/* Returns TRUE when name1 is a wildcard spec that might match yann@1: + something name2 can match. We're conservative: we return FALSE yann@1: + only if the prefixes of name1 and name2 are different up to the yann@1: + first wildcard character. */ yann@1: + yann@1: +static bfd_boolean yann@1: +wild_spec_can_overlap (const char *name1, const char *name2) yann@1: +{ yann@1: + size_t prefix1_len = strcspn (name1, "?*["); yann@1: + size_t prefix2_len = strcspn (name2, "?*["); yann@1: + size_t min_prefix_len; yann@1: + yann@1: + /* Note that if there is no wildcard character, then we treat the yann@1: + terminating 0 as part of the prefix. Thus ".text" won't match yann@1: + ".text." or ".text.*", for example. */ yann@1: + if (name1[prefix1_len] == '\0') yann@1: + prefix1_len++; yann@1: + if (name2[prefix2_len] == '\0') yann@1: + prefix2_len++; yann@1: + yann@1: + min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len; yann@1: + yann@1: + return memcmp (name1, name2, min_prefix_len) == 0; yann@1: +} yann@1: + yann@1: +/* Select specialized code to handle various kinds of wildcard yann@1: + statements. */ yann@1: + yann@1: +static void yann@1: +analyze_walk_wild_section_handler (lang_wild_statement_type *ptr) yann@1: +{ yann@1: + int sec_count = 0; yann@1: + int wild_name_count = 0; yann@1: + struct wildcard_list *sec; yann@1: + int signature; yann@1: + int data_counter; yann@1: + yann@1: + ptr->walk_wild_section_handler = walk_wild_section_general; yann@1: + yann@1: + /* Count how many wildcard_specs there are, and how many of those yann@1: + actually use wildcards in the name. Also, bail out if any of the yann@1: + wildcard names are NULL. (Can this actually happen? yann@1: + walk_wild_section used to test for it.) And bail out if any yann@1: + of the wildcards are more complex than a simple string yann@1: + ending in a single '*'. */ yann@1: + for (sec = ptr->section_list; sec != NULL; sec = sec->next) yann@1: + { yann@1: + ++sec_count; yann@1: + if (sec->spec.name == NULL) yann@1: + return; yann@1: + if (wildcardp (sec->spec.name)) yann@1: + { yann@1: + ++wild_name_count; yann@1: + if (!is_simple_wild (sec->spec.name)) yann@1: + return; yann@1: + } yann@1: + } yann@1: + yann@1: + /* The zero-spec case would be easy to optimize but it doesn't yann@1: + happen in practice. Likewise, more than 4 specs doesn't yann@1: + happen in practice. */ yann@1: + if (sec_count == 0 || sec_count > 4) yann@1: + return; yann@1: + yann@1: + /* Check that no two specs can match the same section. */ yann@1: + for (sec = ptr->section_list; sec != NULL; sec = sec->next) yann@1: + { yann@1: + struct wildcard_list *sec2; yann@1: + for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next) yann@1: + { yann@1: + if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name)) yann@1: + return; yann@1: + } yann@1: + } yann@1: + yann@1: + signature = (sec_count << 8) + wild_name_count; yann@1: + switch (signature) yann@1: + { yann@1: + case 0x0100: yann@1: + ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0; yann@1: + break; yann@1: + case 0x0101: yann@1: + ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1; yann@1: + break; yann@1: + case 0x0201: yann@1: + ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1; yann@1: + break; yann@1: + case 0x0302: yann@1: + ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2; yann@1: + break; yann@1: + case 0x0402: yann@1: + ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2; yann@1: + break; yann@1: + default: yann@1: + return; yann@1: + } yann@1: + yann@1: + /* Now fill the data array with pointers to the specs, first the yann@1: + specs with non-wildcard names, then the specs with wildcard yann@1: + names. It's OK to process the specs in different order from the yann@1: + given order, because we've already determined that no section yann@1: + will match more than one spec. */ yann@1: + data_counter = 0; yann@1: + for (sec = ptr->section_list; sec != NULL; sec = sec->next) yann@1: + if (!wildcardp (sec->spec.name)) yann@1: + ptr->handler_data[data_counter++] = sec; yann@1: + for (sec = ptr->section_list; sec != NULL; sec = sec->next) yann@1: + if (wildcardp (sec->spec.name)) yann@1: + ptr->handler_data[data_counter++] = sec; yann@1: +} yann@1: + yann@1: /* Handle a wild statement for a single file F. */ yann@1: yann@1: static void yann@1: @@ -4353,6 +4737,7 @@ yann@1: new->section_list = section_list; yann@1: new->keep_sections = keep_sections; yann@1: lang_list_init (&new->children); yann@1: + analyze_walk_wild_section_handler (new); yann@1: } yann@1: yann@1: void yann@1: --- binutils-2.15/ld/ldlang.h.old 2004-05-17 15:36:16.000000000 -0400 yann@1: +++ binutils-2.15/ld/ldlang.h 2006-01-23 13:32:33.653292000 -0500 yann@1: @@ -295,7 +295,17 @@ yann@1: union lang_statement_union *file; yann@1: } lang_afile_asection_pair_statement_type; yann@1: yann@1: -typedef struct lang_wild_statement_struct yann@1: +typedef struct lang_wild_statement_struct lang_wild_statement_type; yann@1: + yann@1: +typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *, yann@1: + asection *, lang_input_statement_type *, void *); yann@1: + yann@1: +typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *, yann@1: + lang_input_statement_type *, yann@1: + callback_t callback, yann@1: + void *data); yann@1: + yann@1: +struct lang_wild_statement_struct yann@1: { yann@1: lang_statement_header_type header; yann@1: const char *filename; yann@1: @@ -303,7 +313,10 @@ yann@1: struct wildcard_list *section_list; yann@1: bfd_boolean keep_sections; yann@1: lang_statement_list_type children; yann@1: -} lang_wild_statement_type; yann@1: + yann@1: + walk_wild_section_handler_t walk_wild_section_handler; yann@1: + struct wildcard_list *handler_data[4]; yann@1: +}; yann@1: yann@1: typedef struct lang_address_statement_struct yann@1: {