patches/binutils/2.15/240-ld-callahan.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Mon Jul 28 21:32:33 2008 +0000 (2008-07-28)
changeset 747 d3e603e7c17c
parent 745 patches/binutils/2.15/790-ld-callahan.patch@e445c00d134d
permissions -rw-r--r--
Fourth step at renaming patches: renumber all patches with a 10-step.
     1 Signed-off-by: dank@kegel.com
     2 Fixes ld speed issue. 
     3 See http://weblogs.mozillazine.org/roc/archives/2005/02/optimizing_gnu.html
     4 See thread "Re: optimizations for 3x speedup in ld",
     5 http://sources.redhat.com/ml/binutils/2005-03/msg00847.html
     6 
     7 Wildcard section matching enhancement, backported from the binutils CVS tree.
     8 Here's the CVS log comment from the original change to ldlang.c:
     9 
    10 revision 1.177
    11 date: 2005/04/06 15:33:02;  author: jakub;  state: Exp;  lines: +438 -51
    12 2005-04-06  Jakub Jelinek  <jakub@redhat.com>
    13 
    14         * ldlang.c: Formatting.
    15         (walk_wild_consider_section): Remember return value from wildcardp.
    16         (is_simple_wild): Use strcspn instead of 2 strpbrk calls and strlen.
    17         (wild_spec_can_overlap): Use strcspn instead of strpbrk and strlen.
    18 
    19 2005-04-06  Robert O'Callahan  <rocallahan@novell.com>
    20 
    21         * ld.h (lean_section_userdata_type): Remove.
    22         (fat_section_userdata_type): Remove file field.
    23         (SECTION_USERDATA_SIZE): Remove.
    24         * ldlang.c (init_os): Eliminate initialization of unused
    25         lean_section_userdata_type.
    26 
    27         * ldlang.h (callback_t, walk_wild_section_handler_t): New
    28         typedefs.
    29         (struct lang_wild_statement_struct): Add walk_wild_section_handler
    30         and handler_data fields.
    31         * ldlang.c (callback_t): Removed.
    32         (walk_wild_consider_section, walk_wild_section_general,
    33         section_iterator_callback, find_section, is_simple_wild,
    34         match_simple_wild, walk_wild_section_specs1_wild0,
    35         walk_wild_section_specs1_wild1, walk_wild_section_specs2_wild1,
    36         walk_wild_section_specs3_wild2, walk_wild_section_specs4_wild2,
    37         wild_spec_can_overlap, analyze_walk_wild_section_handler): New
    38         functions.
    39         (lang_add_wild): Call analyze_walk_wild_section_handler.
    40         (walk_wild_section): Renamed to walk_wild_section_general and
    41         created a wrapper function.
    42         (section_iterator_callback_data): New typedef.
    43 
    44 Note that bfd_get_section_by_name_if didn't exist in 2.15, so it was backported
    45 as well.
    46 
    47 --- binutils-2.15/bfd/bfd-in2.h.old	2004-05-17 15:35:56.000000000 -0400
    48 +++ binutils-2.15/bfd/bfd-in2.h	2006-02-09 11:54:45.989940000 -0500
    49 @@ -1425,6 +1425,10 @@
    50  
    51  asection *bfd_get_section_by_name (bfd *abfd, const char *name);
    52  
    53 +asection *bfd_get_section_by_name_if (bfd *abfd, const char *name,
    54 +   bfd_boolean (*operation) (bfd *, asection *, void *),
    55 +   void *user_storage);
    56 +
    57  char *bfd_get_unique_section_name
    58     (bfd *abfd, const char *templat, int *count);
    59  
    60 --- binutils-2.15/bfd/section.c.old	2003-12-01 01:33:01.000000000 -0500
    61 +++ binutils-2.15/bfd/section.c	2006-01-23 14:16:54.768993000 -0500
    62 @@ -801,6 +801,57 @@
    63  
    64  /*
    65  FUNCTION
    66 +	bfd_get_section_by_name_if
    67 +
    68 +SYNOPSIS
    69 +	asection *bfd_get_section_by_name_if
    70 +	  (bfd *abfd,
    71 +	   const char *name,
    72 +	   bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
    73 +	   void *obj);
    74 +
    75 +DESCRIPTION
    76 +	Call the provided function @var{func} for each section
    77 +	attached to the BFD @var{abfd} whose name matches @var{name},
    78 +	passing @var{obj} as an argument. The function will be called
    79 +	as if by
    80 +
    81 +|	func (abfd, the_section, obj);
    82 +
    83 +	It returns the first section for which @var{func} returns true,
    84 +	otherwise <<NULL>>.
    85 +
    86 +*/
    87 +
    88 +asection *
    89 +bfd_get_section_by_name_if (bfd *abfd, const char *name,
    90 +			    bfd_boolean (*operation) (bfd *,
    91 +						      asection *,
    92 +						      void *),
    93 +			    void *user_storage)
    94 +{
    95 +  struct section_hash_entry *sh;
    96 +  unsigned long hash;
    97 +
    98 +  sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE);
    99 +  if (sh == NULL)
   100 +    return NULL;
   101 +
   102 +  hash = sh->root.hash;
   103 +  do
   104 +    {
   105 +      if ((*operation) (abfd, &sh->section, user_storage))
   106 +	return &sh->section;
   107 +      sh = (struct section_hash_entry *) sh->root.next;
   108 +    }
   109 +  while (sh != NULL && sh->root.hash == hash
   110 +	 && strcmp (sh->root.string, name) == 0);
   111 +
   112 +  return NULL;
   113 +}
   114 +
   115 +/*
   116 +FUNCTION
   117  	bfd_get_unique_section_name
   118  
   119  SYNOPSIS
   120 --- binutils-2.15/ld/ldlang.c.old	2004-05-17 15:36:16.000000000 -0400
   121 +++ binutils-2.15/ld/ldlang.c	2006-01-23 13:40:12.745499000 -0500
   122 @@ -81,9 +81,6 @@
   123  static void lang_record_phdrs (void);
   124  static void lang_do_version_exports_section (void);
   125  
   126 -typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   127 -			    asection *, lang_input_statement_type *, void *);
   128 -
   129  /* Exported variables.  */
   130  lang_output_section_statement_type *abs_output_section;
   131  lang_statement_list_type lang_output_section_statement;
   132 @@ -138,21 +135,71 @@
   133  
   134  /* Generic traversal routines for finding matching sections.  */
   135  
   136 +/* Try processing a section against a wildcard.  This just calls
   137 +   the callback unless the filename exclusion list is present
   138 +   and excludes the file.  It's hardly ever present so this
   139 +   function is very fast.  */
   140 +
   141 +static void
   142 +walk_wild_consider_section (lang_wild_statement_type *ptr,
   143 +			    lang_input_statement_type *file,
   144 +			    asection *s,
   145 +			    struct wildcard_list *sec,
   146 +			    callback_t callback,
   147 +			    void *data)
   148 +{
   149 +  bfd_boolean skip = FALSE;
   150 +  struct name_list *list_tmp;
   151 +
   152 +  /* Don't process sections from files which were
   153 +     excluded.  */
   154 +  for (list_tmp = sec->spec.exclude_name_list;
   155 +       list_tmp;
   156 +       list_tmp = list_tmp->next)
   157 +    {
   158 +      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
   159 +      if (is_wildcard)
   160 +	skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   161 +      else
   162 +	skip = strcmp (list_tmp->name, file->filename) == 0;
   163 +
   164 +      /* If this file is part of an archive, and the archive is
   165 +	 excluded, exclude this file.  */
   166 +      if (! skip && file->the_bfd != NULL
   167 +	  && file->the_bfd->my_archive != NULL
   168 +	  && file->the_bfd->my_archive->filename != NULL)
   169 +	{
   170 +	  if (is_wildcard)
   171 +	    skip = fnmatch (list_tmp->name,
   172 +			    file->the_bfd->my_archive->filename,
   173 +			    0) == 0;
   174 +	  else
   175 +	    skip = strcmp (list_tmp->name,
   176 +			   file->the_bfd->my_archive->filename) == 0;
   177 +	}
   178 +
   179 +      if (skip)
   180 +	break;
   181 +    }
   182 +
   183 +  if (!skip)
   184 +    (*callback) (ptr, sec, s, file, data);
   185 +}
   186 +
   187 +/* Lowest common denominator routine that can handle everything correctly,
   188 +   but slowly.  */
   189 +
   190  static void
   191 -walk_wild_section (lang_wild_statement_type *ptr,
   192 -		   lang_input_statement_type *file,
   193 -		   callback_t callback,
   194 -		   void *data)
   195 +walk_wild_section_general (lang_wild_statement_type *ptr,
   196 +			   lang_input_statement_type *file,
   197 +			   callback_t callback,
   198 +			   void *data)
   199  {
   200    asection *s;
   201 -
   202 -  if (file->just_syms_flag)
   203 -    return;
   204 +  struct wildcard_list *sec;
   205  
   206    for (s = file->the_bfd->sections; s != NULL; s = s->next)
   207      {
   208 -      struct wildcard_list *sec;
   209 -
   210        sec = ptr->section_list;
   211        if (sec == NULL)
   212  	(*callback) (ptr, sec, s, file, data);
   213 @@ -160,39 +207,8 @@
   214        while (sec != NULL)
   215  	{
   216  	  bfd_boolean skip = FALSE;
   217 -	  struct name_list *list_tmp;
   218 -
   219 -	  /* Don't process sections from files which were
   220 -	     excluded.  */
   221 -	  for (list_tmp = sec->spec.exclude_name_list;
   222 -	       list_tmp;
   223 -	       list_tmp = list_tmp->next)
   224 -	    {
   225 -	      if (wildcardp (list_tmp->name))
   226 -		skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   227 -	      else
   228 -		skip = strcmp (list_tmp->name, file->filename) == 0;
   229 -
   230 -	      /* If this file is part of an archive, and the archive is
   231 -		 excluded, exclude this file.  */
   232 -	      if (! skip && file->the_bfd != NULL
   233 -		  && file->the_bfd->my_archive != NULL
   234 -		  && file->the_bfd->my_archive->filename != NULL)
   235 -		{
   236 -		  if (wildcardp (list_tmp->name))
   237 -		    skip = fnmatch (list_tmp->name,
   238 -				    file->the_bfd->my_archive->filename,
   239 -				    0) == 0;
   240 -		  else
   241 -		    skip = strcmp (list_tmp->name,
   242 -				   file->the_bfd->my_archive->filename) == 0;
   243 -		}
   244 -
   245 -	      if (skip)
   246 -		break;
   247 -	    }
   248  
   249 -	  if (!skip && sec->spec.name != NULL)
   250 +	  if (sec->spec.name != NULL)
   251  	    {
   252  	      const char *sname = bfd_get_section_name (file->the_bfd, s);
   253  
   254 @@ -203,13 +219,381 @@
   255  	    }
   256  
   257  	  if (!skip)
   258 -	    (*callback) (ptr, sec, s, file, data);
   259 +	    walk_wild_consider_section (ptr, file, s, sec, callback, data);
   260  
   261  	  sec = sec->next;
   262  	}
   263      }
   264  }
   265  
   266 +/* Routines to find a single section given its name.  If there's more
   267 +   than one section with that name, we report that.  */
   268 +
   269 +typedef struct
   270 +{
   271 +  asection *found_section;
   272 +  bfd_boolean multiple_sections_found;
   273 +} section_iterator_callback_data;
   274 +
   275 +static bfd_boolean
   276 +section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
   277 +{
   278 +  section_iterator_callback_data *d = data;
   279 +
   280 +  if (d->found_section != NULL)
   281 +    {
   282 +      d->multiple_sections_found = TRUE;
   283 +      return TRUE;
   284 +    }
   285 +
   286 +  d->found_section = s;
   287 +  return FALSE;
   288 +}
   289 +
   290 +static asection *
   291 +find_section (lang_input_statement_type *file,
   292 +	      struct wildcard_list *sec,
   293 +	      bfd_boolean *multiple_sections_found)
   294 +{
   295 +  section_iterator_callback_data cb_data = { NULL, FALSE };
   296 +
   297 +  bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, 
   298 +			      section_iterator_callback, &cb_data);
   299 +  *multiple_sections_found = cb_data.multiple_sections_found;
   300 +  return cb_data.found_section;
   301 +}
   302 +
   303 +/* Code for handling simple wildcards without going through fnmatch,
   304 +   which can be expensive because of charset translations etc.  */
   305 +
   306 +/* A simple wild is a literal string followed by a single '*',
   307 +   where the literal part is at least 4 characters long.  */
   308 +
   309 +static bfd_boolean
   310 +is_simple_wild (const char *name)
   311 +{
   312 +  size_t len = strcspn (name, "*?[");
   313 +  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
   314 +}
   315 +
   316 +static bfd_boolean
   317 +match_simple_wild (const char *pattern, const char *name)
   318 +{
   319 +  /* The first four characters of the pattern are guaranteed valid
   320 +     non-wildcard characters.  So we can go faster.  */
   321 +  if (pattern[0] != name[0] || pattern[1] != name[1]
   322 +      || pattern[2] != name[2] || pattern[3] != name[3])
   323 +    return FALSE;
   324 +
   325 +  pattern += 4;
   326 +  name += 4;
   327 +  while (*pattern != '*')
   328 +    if (*name++ != *pattern++)
   329 +      return FALSE;
   330 +
   331 +  return TRUE;
   332 +}
   333 +
   334 +/* Specialized, optimized routines for handling different kinds of
   335 +   wildcards */
   336 +
   337 +static void
   338 +walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
   339 +				lang_input_statement_type *file,
   340 +				callback_t callback,
   341 +				void *data)
   342 +{
   343 +  /* We can just do a hash lookup for the section with the right name.
   344 +     But if that lookup discovers more than one section with the name
   345 +     (should be rare), we fall back to the general algorithm because
   346 +     we would otherwise have to sort the sections to make sure they
   347 +     get processed in the bfd's order.  */
   348 +  bfd_boolean multiple_sections_found;
   349 +  struct wildcard_list *sec0 = ptr->handler_data[0];
   350 +  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   351 +
   352 +  if (multiple_sections_found)
   353 +    walk_wild_section_general (ptr, file, callback, data);
   354 +  else if (s0)
   355 +    walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
   356 +}
   357 +
   358 +static void
   359 +walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
   360 +				lang_input_statement_type *file,
   361 +				callback_t callback,
   362 +				void *data)
   363 +{
   364 +  asection *s;
   365 +  struct wildcard_list *wildsec0 = ptr->handler_data[0];
   366 +
   367 +  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   368 +    {
   369 +      const char *sname = bfd_get_section_name (file->the_bfd, s);
   370 +      bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
   371 +
   372 +      if (!skip)
   373 +	walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
   374 +    }
   375 +}
   376 +
   377 +static void
   378 +walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
   379 +				lang_input_statement_type *file,
   380 +				callback_t callback,
   381 +				void *data)
   382 +{
   383 +  asection *s;
   384 +  struct wildcard_list *sec0 = ptr->handler_data[0];
   385 +  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   386 +  bfd_boolean multiple_sections_found;
   387 +  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   388 +
   389 +  if (multiple_sections_found)
   390 +    {
   391 +      walk_wild_section_general (ptr, file, callback, data);
   392 +      return;
   393 +    }
   394 +
   395 +  /* Note that if the section was not found, s0 is NULL and
   396 +     we'll simply never succeed the s == s0 test below.  */
   397 +  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   398 +    {
   399 +      /* Recall that in this code path, a section cannot satisfy more
   400 +	 than one spec, so if s == s0 then it cannot match
   401 +	 wildspec1.  */
   402 +      if (s == s0)
   403 +	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   404 +      else
   405 +	{
   406 +	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   407 +	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   408 +
   409 +	  if (!skip)
   410 +	    walk_wild_consider_section (ptr, file, s, wildsec1, callback,
   411 +					data);
   412 +	}
   413 +    }
   414 +}
   415 +
   416 +static void
   417 +walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
   418 +				lang_input_statement_type *file,
   419 +				callback_t callback,
   420 +				void *data)
   421 +{
   422 +  asection *s;
   423 +  struct wildcard_list *sec0 = ptr->handler_data[0];
   424 +  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   425 +  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   426 +  bfd_boolean multiple_sections_found;
   427 +  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   428 +
   429 +  if (multiple_sections_found)
   430 +    {
   431 +      walk_wild_section_general (ptr, file, callback, data);
   432 +      return;
   433 +    }
   434 +
   435 +  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   436 +    {
   437 +      if (s == s0)
   438 +	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   439 +      else
   440 +	{
   441 +	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   442 +	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   443 +
   444 +	  if (!skip)
   445 +	    walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
   446 +	  else
   447 +	    {
   448 +	      skip = !match_simple_wild (wildsec2->spec.name, sname);
   449 +	      if (!skip)
   450 +		walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   451 +					    data);
   452 +	    }
   453 +	}
   454 +    }
   455 +}
   456 +
   457 +static void
   458 +walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
   459 +				lang_input_statement_type *file,
   460 +				callback_t callback,
   461 +				void *data)
   462 +{
   463 +  asection *s;
   464 +  struct wildcard_list *sec0 = ptr->handler_data[0];
   465 +  struct wildcard_list *sec1 = ptr->handler_data[1];
   466 +  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   467 +  struct wildcard_list *wildsec3 = ptr->handler_data[3];
   468 +  bfd_boolean multiple_sections_found;
   469 +  asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
   470 +
   471 +  if (multiple_sections_found)
   472 +    {
   473 +      walk_wild_section_general (ptr, file, callback, data);
   474 +      return;
   475 +    }
   476 +
   477 +  s1 = find_section (file, sec1, &multiple_sections_found);
   478 +  if (multiple_sections_found)
   479 +    {
   480 +      walk_wild_section_general (ptr, file, callback, data);
   481 +      return;
   482 +    }
   483 +
   484 +  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   485 +    {
   486 +      if (s == s0)
   487 +	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   488 +      else
   489 +	if (s == s1)
   490 +	  walk_wild_consider_section (ptr, file, s, sec1, callback, data);
   491 +	else
   492 +	  {
   493 +	    const char *sname = bfd_get_section_name (file->the_bfd, s);
   494 +	    bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
   495 +						   sname);
   496 +
   497 +	    if (!skip)
   498 +	      walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   499 +					  data);
   500 +	    else
   501 +	      {
   502 +		skip = !match_simple_wild (wildsec3->spec.name, sname);
   503 +		if (!skip)
   504 +		  walk_wild_consider_section (ptr, file, s, wildsec3,
   505 +					      callback, data);
   506 +	      }
   507 +	  }
   508 +    }
   509 +}
   510 +
   511 +static void
   512 +walk_wild_section (lang_wild_statement_type *ptr,
   513 +		   lang_input_statement_type *file,
   514 +		   callback_t callback,
   515 +		   void *data)
   516 +{
   517 +  if (file->just_syms_flag)
   518 +    return;
   519 +
   520 +  (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
   521 +}
   522 +
   523 +/* Returns TRUE when name1 is a wildcard spec that might match
   524 +   something name2 can match.  We're conservative: we return FALSE
   525 +   only if the prefixes of name1 and name2 are different up to the
   526 +   first wildcard character.  */
   527 +
   528 +static bfd_boolean
   529 +wild_spec_can_overlap (const char *name1, const char *name2)
   530 +{
   531 +  size_t prefix1_len = strcspn (name1, "?*[");
   532 +  size_t prefix2_len = strcspn (name2, "?*[");
   533 +  size_t min_prefix_len;
   534 +
   535 +  /* Note that if there is no wildcard character, then we treat the
   536 +     terminating 0 as part of the prefix.  Thus ".text" won't match
   537 +     ".text." or ".text.*", for example.  */
   538 +  if (name1[prefix1_len] == '\0')
   539 +    prefix1_len++;
   540 +  if (name2[prefix2_len] == '\0')
   541 +    prefix2_len++;
   542 +
   543 +  min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
   544 +
   545 +  return memcmp (name1, name2, min_prefix_len) == 0;
   546 +}
   547 +
   548 +/* Select specialized code to handle various kinds of wildcard
   549 +   statements.  */
   550 +
   551 +static void
   552 +analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
   553 +{
   554 +  int sec_count = 0;
   555 +  int wild_name_count = 0;
   556 +  struct wildcard_list *sec;
   557 +  int signature;
   558 +  int data_counter;
   559 +
   560 +  ptr->walk_wild_section_handler = walk_wild_section_general;
   561 +
   562 +  /* Count how many wildcard_specs there are, and how many of those
   563 +     actually use wildcards in the name.  Also, bail out if any of the
   564 +     wildcard names are NULL. (Can this actually happen?
   565 +     walk_wild_section used to test for it.)  And bail out if any
   566 +     of the wildcards are more complex than a simple string
   567 +     ending in a single '*'.  */
   568 +  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   569 +    {
   570 +      ++sec_count;
   571 +      if (sec->spec.name == NULL)
   572 +	return;
   573 +      if (wildcardp (sec->spec.name))
   574 +	{
   575 +	  ++wild_name_count;
   576 +	  if (!is_simple_wild (sec->spec.name))
   577 +	    return;
   578 +	}
   579 +    }
   580 +
   581 +  /* The zero-spec case would be easy to optimize but it doesn't
   582 +     happen in practice.  Likewise, more than 4 specs doesn't
   583 +     happen in practice.  */
   584 +  if (sec_count == 0 || sec_count > 4)
   585 +    return;
   586 +
   587 +  /* Check that no two specs can match the same section.  */
   588 +  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   589 +    {
   590 +      struct wildcard_list *sec2;
   591 +      for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
   592 +	{
   593 +	  if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
   594 +	    return;
   595 +	}
   596 +    }
   597 +
   598 +  signature = (sec_count << 8) + wild_name_count;
   599 +  switch (signature)
   600 +    {
   601 +    case 0x0100:
   602 +      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
   603 +      break;
   604 +    case 0x0101:
   605 +      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
   606 +      break;
   607 +    case 0x0201:
   608 +      ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
   609 +      break;
   610 +    case 0x0302:
   611 +      ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
   612 +      break;
   613 +    case 0x0402:
   614 +      ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
   615 +      break;
   616 +    default:
   617 +      return;
   618 +    }
   619 +
   620 +  /* Now fill the data array with pointers to the specs, first the
   621 +     specs with non-wildcard names, then the specs with wildcard
   622 +     names.  It's OK to process the specs in different order from the
   623 +     given order, because we've already determined that no section
   624 +     will match more than one spec.  */
   625 +  data_counter = 0;
   626 +  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   627 +    if (!wildcardp (sec->spec.name))
   628 +      ptr->handler_data[data_counter++] = sec;
   629 +  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   630 +    if (wildcardp (sec->spec.name))
   631 +      ptr->handler_data[data_counter++] = sec;
   632 +}
   633 +
   634  /* Handle a wild statement for a single file F.  */
   635  
   636  static void
   637 @@ -4353,6 +4737,7 @@
   638    new->section_list = section_list;
   639    new->keep_sections = keep_sections;
   640    lang_list_init (&new->children);
   641 +  analyze_walk_wild_section_handler (new);
   642  }
   643  
   644  void
   645 --- binutils-2.15/ld/ldlang.h.old	2004-05-17 15:36:16.000000000 -0400
   646 +++ binutils-2.15/ld/ldlang.h	2006-01-23 13:32:33.653292000 -0500
   647 @@ -295,7 +295,17 @@
   648    union lang_statement_union *file;
   649  } lang_afile_asection_pair_statement_type;
   650  
   651 -typedef struct lang_wild_statement_struct
   652 +typedef struct lang_wild_statement_struct lang_wild_statement_type;
   653 +
   654 +typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   655 +			    asection *, lang_input_statement_type *, void *);
   656 +
   657 +typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
   658 +					     lang_input_statement_type *,
   659 +					     callback_t callback,
   660 +					     void *data);
   661 +
   662 +struct lang_wild_statement_struct
   663  {
   664    lang_statement_header_type header;
   665    const char *filename;
   666 @@ -303,7 +313,10 @@
   667    struct wildcard_list *section_list;
   668    bfd_boolean keep_sections;
   669    lang_statement_list_type children;
   670 -} lang_wild_statement_type;
   671 +
   672 +  walk_wild_section_handler_t walk_wild_section_handler;
   673 +  struct wildcard_list *handler_data[4];
   674 +};
   675  
   676  typedef struct lang_address_statement_struct
   677  {