patches/binutils/2.15/790-ld-callahan.patch
changeset 745 e445c00d134d
parent 402 197e1b49586e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/patches/binutils/2.15/790-ld-callahan.patch	Mon Jul 28 20:17:48 2008 +0000
     1.3 @@ -0,0 +1,677 @@
     1.4 +Signed-off-by: dank@kegel.com
     1.5 +Fixes ld speed issue. 
     1.6 +See http://weblogs.mozillazine.org/roc/archives/2005/02/optimizing_gnu.html
     1.7 +See thread "Re: optimizations for 3x speedup in ld",
     1.8 +http://sources.redhat.com/ml/binutils/2005-03/msg00847.html
     1.9 +
    1.10 +Wildcard section matching enhancement, backported from the binutils CVS tree.
    1.11 +Here's the CVS log comment from the original change to ldlang.c:
    1.12 +
    1.13 +revision 1.177
    1.14 +date: 2005/04/06 15:33:02;  author: jakub;  state: Exp;  lines: +438 -51
    1.15 +2005-04-06  Jakub Jelinek  <jakub@redhat.com>
    1.16 +
    1.17 +        * ldlang.c: Formatting.
    1.18 +        (walk_wild_consider_section): Remember return value from wildcardp.
    1.19 +        (is_simple_wild): Use strcspn instead of 2 strpbrk calls and strlen.
    1.20 +        (wild_spec_can_overlap): Use strcspn instead of strpbrk and strlen.
    1.21 +
    1.22 +2005-04-06  Robert O'Callahan  <rocallahan@novell.com>
    1.23 +
    1.24 +        * ld.h (lean_section_userdata_type): Remove.
    1.25 +        (fat_section_userdata_type): Remove file field.
    1.26 +        (SECTION_USERDATA_SIZE): Remove.
    1.27 +        * ldlang.c (init_os): Eliminate initialization of unused
    1.28 +        lean_section_userdata_type.
    1.29 +
    1.30 +        * ldlang.h (callback_t, walk_wild_section_handler_t): New
    1.31 +        typedefs.
    1.32 +        (struct lang_wild_statement_struct): Add walk_wild_section_handler
    1.33 +        and handler_data fields.
    1.34 +        * ldlang.c (callback_t): Removed.
    1.35 +        (walk_wild_consider_section, walk_wild_section_general,
    1.36 +        section_iterator_callback, find_section, is_simple_wild,
    1.37 +        match_simple_wild, walk_wild_section_specs1_wild0,
    1.38 +        walk_wild_section_specs1_wild1, walk_wild_section_specs2_wild1,
    1.39 +        walk_wild_section_specs3_wild2, walk_wild_section_specs4_wild2,
    1.40 +        wild_spec_can_overlap, analyze_walk_wild_section_handler): New
    1.41 +        functions.
    1.42 +        (lang_add_wild): Call analyze_walk_wild_section_handler.
    1.43 +        (walk_wild_section): Renamed to walk_wild_section_general and
    1.44 +        created a wrapper function.
    1.45 +        (section_iterator_callback_data): New typedef.
    1.46 +
    1.47 +Note that bfd_get_section_by_name_if didn't exist in 2.15, so it was backported
    1.48 +as well.
    1.49 +
    1.50 +--- binutils-2.15/bfd/bfd-in2.h.old	2004-05-17 15:35:56.000000000 -0400
    1.51 ++++ binutils-2.15/bfd/bfd-in2.h	2006-02-09 11:54:45.989940000 -0500
    1.52 +@@ -1425,6 +1425,10 @@
    1.53 + 
    1.54 + asection *bfd_get_section_by_name (bfd *abfd, const char *name);
    1.55 + 
    1.56 ++asection *bfd_get_section_by_name_if (bfd *abfd, const char *name,
    1.57 ++   bfd_boolean (*operation) (bfd *, asection *, void *),
    1.58 ++   void *user_storage);
    1.59 ++
    1.60 + char *bfd_get_unique_section_name
    1.61 +    (bfd *abfd, const char *templat, int *count);
    1.62 + 
    1.63 +--- binutils-2.15/bfd/section.c.old	2003-12-01 01:33:01.000000000 -0500
    1.64 ++++ binutils-2.15/bfd/section.c	2006-01-23 14:16:54.768993000 -0500
    1.65 +@@ -801,6 +801,57 @@
    1.66 + 
    1.67 + /*
    1.68 + FUNCTION
    1.69 ++	bfd_get_section_by_name_if
    1.70 ++
    1.71 ++SYNOPSIS
    1.72 ++	asection *bfd_get_section_by_name_if
    1.73 ++	  (bfd *abfd,
    1.74 ++	   const char *name,
    1.75 ++	   bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
    1.76 ++	   void *obj);
    1.77 ++
    1.78 ++DESCRIPTION
    1.79 ++	Call the provided function @var{func} for each section
    1.80 ++	attached to the BFD @var{abfd} whose name matches @var{name},
    1.81 ++	passing @var{obj} as an argument. The function will be called
    1.82 ++	as if by
    1.83 ++
    1.84 ++|	func (abfd, the_section, obj);
    1.85 ++
    1.86 ++	It returns the first section for which @var{func} returns true,
    1.87 ++	otherwise <<NULL>>.
    1.88 ++
    1.89 ++*/
    1.90 ++
    1.91 ++asection *
    1.92 ++bfd_get_section_by_name_if (bfd *abfd, const char *name,
    1.93 ++			    bfd_boolean (*operation) (bfd *,
    1.94 ++						      asection *,
    1.95 ++						      void *),
    1.96 ++			    void *user_storage)
    1.97 ++{
    1.98 ++  struct section_hash_entry *sh;
    1.99 ++  unsigned long hash;
   1.100 ++
   1.101 ++  sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE);
   1.102 ++  if (sh == NULL)
   1.103 ++    return NULL;
   1.104 ++
   1.105 ++  hash = sh->root.hash;
   1.106 ++  do
   1.107 ++    {
   1.108 ++      if ((*operation) (abfd, &sh->section, user_storage))
   1.109 ++	return &sh->section;
   1.110 ++      sh = (struct section_hash_entry *) sh->root.next;
   1.111 ++    }
   1.112 ++  while (sh != NULL && sh->root.hash == hash
   1.113 ++	 && strcmp (sh->root.string, name) == 0);
   1.114 ++
   1.115 ++  return NULL;
   1.116 ++}
   1.117 ++
   1.118 ++/*
   1.119 ++FUNCTION
   1.120 + 	bfd_get_unique_section_name
   1.121 + 
   1.122 + SYNOPSIS
   1.123 +--- binutils-2.15/ld/ldlang.c.old	2004-05-17 15:36:16.000000000 -0400
   1.124 ++++ binutils-2.15/ld/ldlang.c	2006-01-23 13:40:12.745499000 -0500
   1.125 +@@ -81,9 +81,6 @@
   1.126 + static void lang_record_phdrs (void);
   1.127 + static void lang_do_version_exports_section (void);
   1.128 + 
   1.129 +-typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   1.130 +-			    asection *, lang_input_statement_type *, void *);
   1.131 +-
   1.132 + /* Exported variables.  */
   1.133 + lang_output_section_statement_type *abs_output_section;
   1.134 + lang_statement_list_type lang_output_section_statement;
   1.135 +@@ -138,21 +135,71 @@
   1.136 + 
   1.137 + /* Generic traversal routines for finding matching sections.  */
   1.138 + 
   1.139 ++/* Try processing a section against a wildcard.  This just calls
   1.140 ++   the callback unless the filename exclusion list is present
   1.141 ++   and excludes the file.  It's hardly ever present so this
   1.142 ++   function is very fast.  */
   1.143 ++
   1.144 ++static void
   1.145 ++walk_wild_consider_section (lang_wild_statement_type *ptr,
   1.146 ++			    lang_input_statement_type *file,
   1.147 ++			    asection *s,
   1.148 ++			    struct wildcard_list *sec,
   1.149 ++			    callback_t callback,
   1.150 ++			    void *data)
   1.151 ++{
   1.152 ++  bfd_boolean skip = FALSE;
   1.153 ++  struct name_list *list_tmp;
   1.154 ++
   1.155 ++  /* Don't process sections from files which were
   1.156 ++     excluded.  */
   1.157 ++  for (list_tmp = sec->spec.exclude_name_list;
   1.158 ++       list_tmp;
   1.159 ++       list_tmp = list_tmp->next)
   1.160 ++    {
   1.161 ++      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
   1.162 ++      if (is_wildcard)
   1.163 ++	skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   1.164 ++      else
   1.165 ++	skip = strcmp (list_tmp->name, file->filename) == 0;
   1.166 ++
   1.167 ++      /* If this file is part of an archive, and the archive is
   1.168 ++	 excluded, exclude this file.  */
   1.169 ++      if (! skip && file->the_bfd != NULL
   1.170 ++	  && file->the_bfd->my_archive != NULL
   1.171 ++	  && file->the_bfd->my_archive->filename != NULL)
   1.172 ++	{
   1.173 ++	  if (is_wildcard)
   1.174 ++	    skip = fnmatch (list_tmp->name,
   1.175 ++			    file->the_bfd->my_archive->filename,
   1.176 ++			    0) == 0;
   1.177 ++	  else
   1.178 ++	    skip = strcmp (list_tmp->name,
   1.179 ++			   file->the_bfd->my_archive->filename) == 0;
   1.180 ++	}
   1.181 ++
   1.182 ++      if (skip)
   1.183 ++	break;
   1.184 ++    }
   1.185 ++
   1.186 ++  if (!skip)
   1.187 ++    (*callback) (ptr, sec, s, file, data);
   1.188 ++}
   1.189 ++
   1.190 ++/* Lowest common denominator routine that can handle everything correctly,
   1.191 ++   but slowly.  */
   1.192 ++
   1.193 + static void
   1.194 +-walk_wild_section (lang_wild_statement_type *ptr,
   1.195 +-		   lang_input_statement_type *file,
   1.196 +-		   callback_t callback,
   1.197 +-		   void *data)
   1.198 ++walk_wild_section_general (lang_wild_statement_type *ptr,
   1.199 ++			   lang_input_statement_type *file,
   1.200 ++			   callback_t callback,
   1.201 ++			   void *data)
   1.202 + {
   1.203 +   asection *s;
   1.204 +-
   1.205 +-  if (file->just_syms_flag)
   1.206 +-    return;
   1.207 ++  struct wildcard_list *sec;
   1.208 + 
   1.209 +   for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.210 +     {
   1.211 +-      struct wildcard_list *sec;
   1.212 +-
   1.213 +       sec = ptr->section_list;
   1.214 +       if (sec == NULL)
   1.215 + 	(*callback) (ptr, sec, s, file, data);
   1.216 +@@ -160,39 +207,8 @@
   1.217 +       while (sec != NULL)
   1.218 + 	{
   1.219 + 	  bfd_boolean skip = FALSE;
   1.220 +-	  struct name_list *list_tmp;
   1.221 +-
   1.222 +-	  /* Don't process sections from files which were
   1.223 +-	     excluded.  */
   1.224 +-	  for (list_tmp = sec->spec.exclude_name_list;
   1.225 +-	       list_tmp;
   1.226 +-	       list_tmp = list_tmp->next)
   1.227 +-	    {
   1.228 +-	      if (wildcardp (list_tmp->name))
   1.229 +-		skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   1.230 +-	      else
   1.231 +-		skip = strcmp (list_tmp->name, file->filename) == 0;
   1.232 +-
   1.233 +-	      /* If this file is part of an archive, and the archive is
   1.234 +-		 excluded, exclude this file.  */
   1.235 +-	      if (! skip && file->the_bfd != NULL
   1.236 +-		  && file->the_bfd->my_archive != NULL
   1.237 +-		  && file->the_bfd->my_archive->filename != NULL)
   1.238 +-		{
   1.239 +-		  if (wildcardp (list_tmp->name))
   1.240 +-		    skip = fnmatch (list_tmp->name,
   1.241 +-				    file->the_bfd->my_archive->filename,
   1.242 +-				    0) == 0;
   1.243 +-		  else
   1.244 +-		    skip = strcmp (list_tmp->name,
   1.245 +-				   file->the_bfd->my_archive->filename) == 0;
   1.246 +-		}
   1.247 +-
   1.248 +-	      if (skip)
   1.249 +-		break;
   1.250 +-	    }
   1.251 + 
   1.252 +-	  if (!skip && sec->spec.name != NULL)
   1.253 ++	  if (sec->spec.name != NULL)
   1.254 + 	    {
   1.255 + 	      const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.256 + 
   1.257 +@@ -203,13 +219,381 @@
   1.258 + 	    }
   1.259 + 
   1.260 + 	  if (!skip)
   1.261 +-	    (*callback) (ptr, sec, s, file, data);
   1.262 ++	    walk_wild_consider_section (ptr, file, s, sec, callback, data);
   1.263 + 
   1.264 + 	  sec = sec->next;
   1.265 + 	}
   1.266 +     }
   1.267 + }
   1.268 + 
   1.269 ++/* Routines to find a single section given its name.  If there's more
   1.270 ++   than one section with that name, we report that.  */
   1.271 ++
   1.272 ++typedef struct
   1.273 ++{
   1.274 ++  asection *found_section;
   1.275 ++  bfd_boolean multiple_sections_found;
   1.276 ++} section_iterator_callback_data;
   1.277 ++
   1.278 ++static bfd_boolean
   1.279 ++section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
   1.280 ++{
   1.281 ++  section_iterator_callback_data *d = data;
   1.282 ++
   1.283 ++  if (d->found_section != NULL)
   1.284 ++    {
   1.285 ++      d->multiple_sections_found = TRUE;
   1.286 ++      return TRUE;
   1.287 ++    }
   1.288 ++
   1.289 ++  d->found_section = s;
   1.290 ++  return FALSE;
   1.291 ++}
   1.292 ++
   1.293 ++static asection *
   1.294 ++find_section (lang_input_statement_type *file,
   1.295 ++	      struct wildcard_list *sec,
   1.296 ++	      bfd_boolean *multiple_sections_found)
   1.297 ++{
   1.298 ++  section_iterator_callback_data cb_data = { NULL, FALSE };
   1.299 ++
   1.300 ++  bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, 
   1.301 ++			      section_iterator_callback, &cb_data);
   1.302 ++  *multiple_sections_found = cb_data.multiple_sections_found;
   1.303 ++  return cb_data.found_section;
   1.304 ++}
   1.305 ++
   1.306 ++/* Code for handling simple wildcards without going through fnmatch,
   1.307 ++   which can be expensive because of charset translations etc.  */
   1.308 ++
   1.309 ++/* A simple wild is a literal string followed by a single '*',
   1.310 ++   where the literal part is at least 4 characters long.  */
   1.311 ++
   1.312 ++static bfd_boolean
   1.313 ++is_simple_wild (const char *name)
   1.314 ++{
   1.315 ++  size_t len = strcspn (name, "*?[");
   1.316 ++  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
   1.317 ++}
   1.318 ++
   1.319 ++static bfd_boolean
   1.320 ++match_simple_wild (const char *pattern, const char *name)
   1.321 ++{
   1.322 ++  /* The first four characters of the pattern are guaranteed valid
   1.323 ++     non-wildcard characters.  So we can go faster.  */
   1.324 ++  if (pattern[0] != name[0] || pattern[1] != name[1]
   1.325 ++      || pattern[2] != name[2] || pattern[3] != name[3])
   1.326 ++    return FALSE;
   1.327 ++
   1.328 ++  pattern += 4;
   1.329 ++  name += 4;
   1.330 ++  while (*pattern != '*')
   1.331 ++    if (*name++ != *pattern++)
   1.332 ++      return FALSE;
   1.333 ++
   1.334 ++  return TRUE;
   1.335 ++}
   1.336 ++
   1.337 ++/* Specialized, optimized routines for handling different kinds of
   1.338 ++   wildcards */
   1.339 ++
   1.340 ++static void
   1.341 ++walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
   1.342 ++				lang_input_statement_type *file,
   1.343 ++				callback_t callback,
   1.344 ++				void *data)
   1.345 ++{
   1.346 ++  /* We can just do a hash lookup for the section with the right name.
   1.347 ++     But if that lookup discovers more than one section with the name
   1.348 ++     (should be rare), we fall back to the general algorithm because
   1.349 ++     we would otherwise have to sort the sections to make sure they
   1.350 ++     get processed in the bfd's order.  */
   1.351 ++  bfd_boolean multiple_sections_found;
   1.352 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.353 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.354 ++
   1.355 ++  if (multiple_sections_found)
   1.356 ++    walk_wild_section_general (ptr, file, callback, data);
   1.357 ++  else if (s0)
   1.358 ++    walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
   1.359 ++}
   1.360 ++
   1.361 ++static void
   1.362 ++walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
   1.363 ++				lang_input_statement_type *file,
   1.364 ++				callback_t callback,
   1.365 ++				void *data)
   1.366 ++{
   1.367 ++  asection *s;
   1.368 ++  struct wildcard_list *wildsec0 = ptr->handler_data[0];
   1.369 ++
   1.370 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.371 ++    {
   1.372 ++      const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.373 ++      bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
   1.374 ++
   1.375 ++      if (!skip)
   1.376 ++	walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
   1.377 ++    }
   1.378 ++}
   1.379 ++
   1.380 ++static void
   1.381 ++walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
   1.382 ++				lang_input_statement_type *file,
   1.383 ++				callback_t callback,
   1.384 ++				void *data)
   1.385 ++{
   1.386 ++  asection *s;
   1.387 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.388 ++  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   1.389 ++  bfd_boolean multiple_sections_found;
   1.390 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.391 ++
   1.392 ++  if (multiple_sections_found)
   1.393 ++    {
   1.394 ++      walk_wild_section_general (ptr, file, callback, data);
   1.395 ++      return;
   1.396 ++    }
   1.397 ++
   1.398 ++  /* Note that if the section was not found, s0 is NULL and
   1.399 ++     we'll simply never succeed the s == s0 test below.  */
   1.400 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.401 ++    {
   1.402 ++      /* Recall that in this code path, a section cannot satisfy more
   1.403 ++	 than one spec, so if s == s0 then it cannot match
   1.404 ++	 wildspec1.  */
   1.405 ++      if (s == s0)
   1.406 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.407 ++      else
   1.408 ++	{
   1.409 ++	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.410 ++	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   1.411 ++
   1.412 ++	  if (!skip)
   1.413 ++	    walk_wild_consider_section (ptr, file, s, wildsec1, callback,
   1.414 ++					data);
   1.415 ++	}
   1.416 ++    }
   1.417 ++}
   1.418 ++
   1.419 ++static void
   1.420 ++walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
   1.421 ++				lang_input_statement_type *file,
   1.422 ++				callback_t callback,
   1.423 ++				void *data)
   1.424 ++{
   1.425 ++  asection *s;
   1.426 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.427 ++  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   1.428 ++  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   1.429 ++  bfd_boolean multiple_sections_found;
   1.430 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.431 ++
   1.432 ++  if (multiple_sections_found)
   1.433 ++    {
   1.434 ++      walk_wild_section_general (ptr, file, callback, data);
   1.435 ++      return;
   1.436 ++    }
   1.437 ++
   1.438 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.439 ++    {
   1.440 ++      if (s == s0)
   1.441 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.442 ++      else
   1.443 ++	{
   1.444 ++	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.445 ++	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   1.446 ++
   1.447 ++	  if (!skip)
   1.448 ++	    walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
   1.449 ++	  else
   1.450 ++	    {
   1.451 ++	      skip = !match_simple_wild (wildsec2->spec.name, sname);
   1.452 ++	      if (!skip)
   1.453 ++		walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   1.454 ++					    data);
   1.455 ++	    }
   1.456 ++	}
   1.457 ++    }
   1.458 ++}
   1.459 ++
   1.460 ++static void
   1.461 ++walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
   1.462 ++				lang_input_statement_type *file,
   1.463 ++				callback_t callback,
   1.464 ++				void *data)
   1.465 ++{
   1.466 ++  asection *s;
   1.467 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.468 ++  struct wildcard_list *sec1 = ptr->handler_data[1];
   1.469 ++  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   1.470 ++  struct wildcard_list *wildsec3 = ptr->handler_data[3];
   1.471 ++  bfd_boolean multiple_sections_found;
   1.472 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
   1.473 ++
   1.474 ++  if (multiple_sections_found)
   1.475 ++    {
   1.476 ++      walk_wild_section_general (ptr, file, callback, data);
   1.477 ++      return;
   1.478 ++    }
   1.479 ++
   1.480 ++  s1 = find_section (file, sec1, &multiple_sections_found);
   1.481 ++  if (multiple_sections_found)
   1.482 ++    {
   1.483 ++      walk_wild_section_general (ptr, file, callback, data);
   1.484 ++      return;
   1.485 ++    }
   1.486 ++
   1.487 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.488 ++    {
   1.489 ++      if (s == s0)
   1.490 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.491 ++      else
   1.492 ++	if (s == s1)
   1.493 ++	  walk_wild_consider_section (ptr, file, s, sec1, callback, data);
   1.494 ++	else
   1.495 ++	  {
   1.496 ++	    const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.497 ++	    bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
   1.498 ++						   sname);
   1.499 ++
   1.500 ++	    if (!skip)
   1.501 ++	      walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   1.502 ++					  data);
   1.503 ++	    else
   1.504 ++	      {
   1.505 ++		skip = !match_simple_wild (wildsec3->spec.name, sname);
   1.506 ++		if (!skip)
   1.507 ++		  walk_wild_consider_section (ptr, file, s, wildsec3,
   1.508 ++					      callback, data);
   1.509 ++	      }
   1.510 ++	  }
   1.511 ++    }
   1.512 ++}
   1.513 ++
   1.514 ++static void
   1.515 ++walk_wild_section (lang_wild_statement_type *ptr,
   1.516 ++		   lang_input_statement_type *file,
   1.517 ++		   callback_t callback,
   1.518 ++		   void *data)
   1.519 ++{
   1.520 ++  if (file->just_syms_flag)
   1.521 ++    return;
   1.522 ++
   1.523 ++  (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
   1.524 ++}
   1.525 ++
   1.526 ++/* Returns TRUE when name1 is a wildcard spec that might match
   1.527 ++   something name2 can match.  We're conservative: we return FALSE
   1.528 ++   only if the prefixes of name1 and name2 are different up to the
   1.529 ++   first wildcard character.  */
   1.530 ++
   1.531 ++static bfd_boolean
   1.532 ++wild_spec_can_overlap (const char *name1, const char *name2)
   1.533 ++{
   1.534 ++  size_t prefix1_len = strcspn (name1, "?*[");
   1.535 ++  size_t prefix2_len = strcspn (name2, "?*[");
   1.536 ++  size_t min_prefix_len;
   1.537 ++
   1.538 ++  /* Note that if there is no wildcard character, then we treat the
   1.539 ++     terminating 0 as part of the prefix.  Thus ".text" won't match
   1.540 ++     ".text." or ".text.*", for example.  */
   1.541 ++  if (name1[prefix1_len] == '\0')
   1.542 ++    prefix1_len++;
   1.543 ++  if (name2[prefix2_len] == '\0')
   1.544 ++    prefix2_len++;
   1.545 ++
   1.546 ++  min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
   1.547 ++
   1.548 ++  return memcmp (name1, name2, min_prefix_len) == 0;
   1.549 ++}
   1.550 ++
   1.551 ++/* Select specialized code to handle various kinds of wildcard
   1.552 ++   statements.  */
   1.553 ++
   1.554 ++static void
   1.555 ++analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
   1.556 ++{
   1.557 ++  int sec_count = 0;
   1.558 ++  int wild_name_count = 0;
   1.559 ++  struct wildcard_list *sec;
   1.560 ++  int signature;
   1.561 ++  int data_counter;
   1.562 ++
   1.563 ++  ptr->walk_wild_section_handler = walk_wild_section_general;
   1.564 ++
   1.565 ++  /* Count how many wildcard_specs there are, and how many of those
   1.566 ++     actually use wildcards in the name.  Also, bail out if any of the
   1.567 ++     wildcard names are NULL. (Can this actually happen?
   1.568 ++     walk_wild_section used to test for it.)  And bail out if any
   1.569 ++     of the wildcards are more complex than a simple string
   1.570 ++     ending in a single '*'.  */
   1.571 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.572 ++    {
   1.573 ++      ++sec_count;
   1.574 ++      if (sec->spec.name == NULL)
   1.575 ++	return;
   1.576 ++      if (wildcardp (sec->spec.name))
   1.577 ++	{
   1.578 ++	  ++wild_name_count;
   1.579 ++	  if (!is_simple_wild (sec->spec.name))
   1.580 ++	    return;
   1.581 ++	}
   1.582 ++    }
   1.583 ++
   1.584 ++  /* The zero-spec case would be easy to optimize but it doesn't
   1.585 ++     happen in practice.  Likewise, more than 4 specs doesn't
   1.586 ++     happen in practice.  */
   1.587 ++  if (sec_count == 0 || sec_count > 4)
   1.588 ++    return;
   1.589 ++
   1.590 ++  /* Check that no two specs can match the same section.  */
   1.591 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.592 ++    {
   1.593 ++      struct wildcard_list *sec2;
   1.594 ++      for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
   1.595 ++	{
   1.596 ++	  if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
   1.597 ++	    return;
   1.598 ++	}
   1.599 ++    }
   1.600 ++
   1.601 ++  signature = (sec_count << 8) + wild_name_count;
   1.602 ++  switch (signature)
   1.603 ++    {
   1.604 ++    case 0x0100:
   1.605 ++      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
   1.606 ++      break;
   1.607 ++    case 0x0101:
   1.608 ++      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
   1.609 ++      break;
   1.610 ++    case 0x0201:
   1.611 ++      ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
   1.612 ++      break;
   1.613 ++    case 0x0302:
   1.614 ++      ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
   1.615 ++      break;
   1.616 ++    case 0x0402:
   1.617 ++      ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
   1.618 ++      break;
   1.619 ++    default:
   1.620 ++      return;
   1.621 ++    }
   1.622 ++
   1.623 ++  /* Now fill the data array with pointers to the specs, first the
   1.624 ++     specs with non-wildcard names, then the specs with wildcard
   1.625 ++     names.  It's OK to process the specs in different order from the
   1.626 ++     given order, because we've already determined that no section
   1.627 ++     will match more than one spec.  */
   1.628 ++  data_counter = 0;
   1.629 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.630 ++    if (!wildcardp (sec->spec.name))
   1.631 ++      ptr->handler_data[data_counter++] = sec;
   1.632 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.633 ++    if (wildcardp (sec->spec.name))
   1.634 ++      ptr->handler_data[data_counter++] = sec;
   1.635 ++}
   1.636 ++
   1.637 + /* Handle a wild statement for a single file F.  */
   1.638 + 
   1.639 + static void
   1.640 +@@ -4353,6 +4737,7 @@
   1.641 +   new->section_list = section_list;
   1.642 +   new->keep_sections = keep_sections;
   1.643 +   lang_list_init (&new->children);
   1.644 ++  analyze_walk_wild_section_handler (new);
   1.645 + }
   1.646 + 
   1.647 + void
   1.648 +--- binutils-2.15/ld/ldlang.h.old	2004-05-17 15:36:16.000000000 -0400
   1.649 ++++ binutils-2.15/ld/ldlang.h	2006-01-23 13:32:33.653292000 -0500
   1.650 +@@ -295,7 +295,17 @@
   1.651 +   union lang_statement_union *file;
   1.652 + } lang_afile_asection_pair_statement_type;
   1.653 + 
   1.654 +-typedef struct lang_wild_statement_struct
   1.655 ++typedef struct lang_wild_statement_struct lang_wild_statement_type;
   1.656 ++
   1.657 ++typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   1.658 ++			    asection *, lang_input_statement_type *, void *);
   1.659 ++
   1.660 ++typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
   1.661 ++					     lang_input_statement_type *,
   1.662 ++					     callback_t callback,
   1.663 ++					     void *data);
   1.664 ++
   1.665 ++struct lang_wild_statement_struct
   1.666 + {
   1.667 +   lang_statement_header_type header;
   1.668 +   const char *filename;
   1.669 +@@ -303,7 +313,10 @@
   1.670 +   struct wildcard_list *section_list;
   1.671 +   bfd_boolean keep_sections;
   1.672 +   lang_statement_list_type children;
   1.673 +-} lang_wild_statement_type;
   1.674 ++
   1.675 ++  walk_wild_section_handler_t walk_wild_section_handler;
   1.676 ++  struct wildcard_list *handler_data[4];
   1.677 ++};
   1.678 + 
   1.679 + typedef struct lang_address_statement_struct
   1.680 + {