patches/binutils/2.16.1a/130-callahan.patch
changeset 2664 346263a07115
parent 402 197e1b49586e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/patches/binutils/2.16.1a/130-callahan.patch	Sun Sep 11 18:18:53 2011 +0200
     1.3 @@ -0,0 +1,693 @@
     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 +
    1.48 +Index: src/ld/ld.h
    1.49 +===================================================================
    1.50 +RCS file: /cvs/src/src/ld/ld.h,v
    1.51 +retrieving revision 1.26
    1.52 +retrieving revision 1.27
    1.53 +diff -u -r1.26 -r1.27
    1.54 +--- binutils/ld/ld.h.old	16 Mar 2005 21:52:42 -0000	1.26
    1.55 ++++ binutils/ld/ld.h	6 Apr 2005 15:33:02 -0000	1.27
    1.56 +@@ -1,6 +1,6 @@
    1.57 + /* ld.h -- general linker header file
    1.58 +    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
    1.59 +-   2001, 2002, 2003, 2004
    1.60 ++   2001, 2002, 2003, 2004, 2005
    1.61 +    Free Software Foundation, Inc.
    1.62 + 
    1.63 +    This file is part of GLD, the Gnu Linker.
    1.64 +@@ -89,28 +89,15 @@
    1.65 +   struct map_symbol_def *next;
    1.66 + };
    1.67 + 
    1.68 +-/* Extra information we hold on sections */
    1.69 +-typedef struct lean_user_section_struct {
    1.70 +-  /* For output sections: pointer to the section where this data will go.  */
    1.71 +-  struct lang_input_statement_struct *file;
    1.72 +-} lean_section_userdata_type;
    1.73 +-
    1.74 + /* The initial part of fat_user_section_struct has to be idential with
    1.75 +    lean_user_section_struct.  */
    1.76 + typedef struct fat_user_section_struct {
    1.77 +-  /* For output sections: pointer to the section where this data will go.  */
    1.78 +-  struct lang_input_statement_struct *file;
    1.79 +   /* For input sections, when writing a map file: head / tail of a linked
    1.80 +      list of hash table entries for symbols defined in this section.  */
    1.81 +   struct map_symbol_def *map_symbol_def_head;
    1.82 +   struct map_symbol_def **map_symbol_def_tail;
    1.83 + } fat_section_userdata_type;
    1.84 + 
    1.85 +-#define SECTION_USERDATA_SIZE \
    1.86 +- (command_line.reduce_memory_overheads \
    1.87 +-  ? sizeof (lean_section_userdata_type) \
    1.88 +-  : sizeof (fat_section_userdata_type))
    1.89 +-
    1.90 + #define get_userdata(x) ((x)->userdata)
    1.91 + 
    1.92 + #define BYTE_SIZE	(1)
    1.93 +Index: src/ld/ldlang.c
    1.94 +===================================================================
    1.95 +RCS file: /cvs/src/src/ld/ldlang.c,v
    1.96 +retrieving revision 1.176
    1.97 +retrieving revision 1.177
    1.98 +diff -u -r1.176 -r1.177
    1.99 +--- binutils/ld/ldlang.c.old	18 Mar 2005 13:56:26 -0000	1.176
   1.100 ++++ binutils/ld/ldlang.c	6 Apr 2005 15:33:02 -0000	1.177
   1.101 +@@ -84,9 +84,6 @@
   1.102 + static void lang_record_phdrs (void);
   1.103 + static void lang_do_version_exports_section (void);
   1.104 + 
   1.105 +-typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   1.106 +-			    asection *, lang_input_statement_type *, void *);
   1.107 +-
   1.108 + /* Exported variables.  */
   1.109 + lang_output_section_statement_type *abs_output_section;
   1.110 + lang_statement_list_type lang_output_section_statement;
   1.111 +@@ -155,21 +152,71 @@
   1.112 + 
   1.113 + /* Generic traversal routines for finding matching sections.  */
   1.114 + 
   1.115 ++/* Try processing a section against a wildcard.  This just calls
   1.116 ++   the callback unless the filename exclusion list is present
   1.117 ++   and excludes the file.  It's hardly ever present so this
   1.118 ++   function is very fast.  */
   1.119 ++
   1.120 ++static void
   1.121 ++walk_wild_consider_section (lang_wild_statement_type *ptr,
   1.122 ++			    lang_input_statement_type *file,
   1.123 ++			    asection *s,
   1.124 ++			    struct wildcard_list *sec,
   1.125 ++			    callback_t callback,
   1.126 ++			    void *data)
   1.127 ++{
   1.128 ++  bfd_boolean skip = FALSE;
   1.129 ++  struct name_list *list_tmp;
   1.130 ++
   1.131 ++  /* Don't process sections from files which were
   1.132 ++     excluded.  */
   1.133 ++  for (list_tmp = sec->spec.exclude_name_list;
   1.134 ++       list_tmp;
   1.135 ++       list_tmp = list_tmp->next)
   1.136 ++    {
   1.137 ++      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
   1.138 ++      if (is_wildcard)
   1.139 ++	skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   1.140 ++      else
   1.141 ++	skip = strcmp (list_tmp->name, file->filename) == 0;
   1.142 ++
   1.143 ++      /* If this file is part of an archive, and the archive is
   1.144 ++	 excluded, exclude this file.  */
   1.145 ++      if (! skip && file->the_bfd != NULL
   1.146 ++	  && file->the_bfd->my_archive != NULL
   1.147 ++	  && file->the_bfd->my_archive->filename != NULL)
   1.148 ++	{
   1.149 ++	  if (is_wildcard)
   1.150 ++	    skip = fnmatch (list_tmp->name,
   1.151 ++			    file->the_bfd->my_archive->filename,
   1.152 ++			    0) == 0;
   1.153 ++	  else
   1.154 ++	    skip = strcmp (list_tmp->name,
   1.155 ++			   file->the_bfd->my_archive->filename) == 0;
   1.156 ++	}
   1.157 ++
   1.158 ++      if (skip)
   1.159 ++	break;
   1.160 ++    }
   1.161 ++
   1.162 ++  if (!skip)
   1.163 ++    (*callback) (ptr, sec, s, file, data);
   1.164 ++}
   1.165 ++
   1.166 ++/* Lowest common denominator routine that can handle everything correctly,
   1.167 ++   but slowly.  */
   1.168 ++
   1.169 + static void
   1.170 +-walk_wild_section (lang_wild_statement_type *ptr,
   1.171 +-		   lang_input_statement_type *file,
   1.172 +-		   callback_t callback,
   1.173 +-		   void *data)
   1.174 ++walk_wild_section_general (lang_wild_statement_type *ptr,
   1.175 ++			   lang_input_statement_type *file,
   1.176 ++			   callback_t callback,
   1.177 ++			   void *data)
   1.178 + {
   1.179 +   asection *s;
   1.180 +-
   1.181 +-  if (file->just_syms_flag)
   1.182 +-    return;
   1.183 ++  struct wildcard_list *sec;
   1.184 + 
   1.185 +   for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.186 +     {
   1.187 +-      struct wildcard_list *sec;
   1.188 +-
   1.189 +       sec = ptr->section_list;
   1.190 +       if (sec == NULL)
   1.191 + 	(*callback) (ptr, sec, s, file, data);
   1.192 +@@ -177,39 +224,8 @@
   1.193 +       while (sec != NULL)
   1.194 + 	{
   1.195 + 	  bfd_boolean skip = FALSE;
   1.196 +-	  struct name_list *list_tmp;
   1.197 + 
   1.198 +-	  /* Don't process sections from files which were
   1.199 +-	     excluded.  */
   1.200 +-	  for (list_tmp = sec->spec.exclude_name_list;
   1.201 +-	       list_tmp;
   1.202 +-	       list_tmp = list_tmp->next)
   1.203 +-	    {
   1.204 +-	      if (wildcardp (list_tmp->name))
   1.205 +-		skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
   1.206 +-	      else
   1.207 +-		skip = strcmp (list_tmp->name, file->filename) == 0;
   1.208 +-
   1.209 +-	      /* If this file is part of an archive, and the archive is
   1.210 +-		 excluded, exclude this file.  */
   1.211 +-	      if (! skip && file->the_bfd != NULL
   1.212 +-		  && file->the_bfd->my_archive != NULL
   1.213 +-		  && file->the_bfd->my_archive->filename != NULL)
   1.214 +-		{
   1.215 +-		  if (wildcardp (list_tmp->name))
   1.216 +-		    skip = fnmatch (list_tmp->name,
   1.217 +-				    file->the_bfd->my_archive->filename,
   1.218 +-				    0) == 0;
   1.219 +-		  else
   1.220 +-		    skip = strcmp (list_tmp->name,
   1.221 +-				   file->the_bfd->my_archive->filename) == 0;
   1.222 +-		}
   1.223 +-
   1.224 +-	      if (skip)
   1.225 +-		break;
   1.226 +-	    }
   1.227 +-
   1.228 +-	  if (!skip && sec->spec.name != NULL)
   1.229 ++	  if (sec->spec.name != NULL)
   1.230 + 	    {
   1.231 + 	      const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.232 + 
   1.233 +@@ -220,13 +236,381 @@
   1.234 + 	    }
   1.235 + 
   1.236 + 	  if (!skip)
   1.237 +-	    (*callback) (ptr, sec, s, file, data);
   1.238 ++	    walk_wild_consider_section (ptr, file, s, sec, callback, data);
   1.239 + 
   1.240 + 	  sec = sec->next;
   1.241 + 	}
   1.242 +     }
   1.243 + }
   1.244 + 
   1.245 ++/* Routines to find a single section given its name.  If there's more
   1.246 ++   than one section with that name, we report that.  */
   1.247 ++
   1.248 ++typedef struct
   1.249 ++{
   1.250 ++  asection *found_section;
   1.251 ++  bfd_boolean multiple_sections_found;
   1.252 ++} section_iterator_callback_data;
   1.253 ++
   1.254 ++static bfd_boolean
   1.255 ++section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
   1.256 ++{
   1.257 ++  section_iterator_callback_data *d = data;
   1.258 ++
   1.259 ++  if (d->found_section != NULL)
   1.260 ++    {
   1.261 ++      d->multiple_sections_found = TRUE;
   1.262 ++      return TRUE;
   1.263 ++    }
   1.264 ++
   1.265 ++  d->found_section = s;
   1.266 ++  return FALSE;
   1.267 ++}
   1.268 ++
   1.269 ++static asection *
   1.270 ++find_section (lang_input_statement_type *file,
   1.271 ++	      struct wildcard_list *sec,
   1.272 ++	      bfd_boolean *multiple_sections_found)
   1.273 ++{
   1.274 ++  section_iterator_callback_data cb_data = { NULL, FALSE };
   1.275 ++
   1.276 ++  bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, 
   1.277 ++			      section_iterator_callback, &cb_data);
   1.278 ++  *multiple_sections_found = cb_data.multiple_sections_found;
   1.279 ++  return cb_data.found_section;
   1.280 ++}
   1.281 ++
   1.282 ++/* Code for handling simple wildcards without going through fnmatch,
   1.283 ++   which can be expensive because of charset translations etc.  */
   1.284 ++
   1.285 ++/* A simple wild is a literal string followed by a single '*',
   1.286 ++   where the literal part is at least 4 characters long.  */
   1.287 ++
   1.288 ++static bfd_boolean
   1.289 ++is_simple_wild (const char *name)
   1.290 ++{
   1.291 ++  size_t len = strcspn (name, "*?[");
   1.292 ++  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
   1.293 ++}
   1.294 ++
   1.295 ++static bfd_boolean
   1.296 ++match_simple_wild (const char *pattern, const char *name)
   1.297 ++{
   1.298 ++  /* The first four characters of the pattern are guaranteed valid
   1.299 ++     non-wildcard characters.  So we can go faster.  */
   1.300 ++  if (pattern[0] != name[0] || pattern[1] != name[1]
   1.301 ++      || pattern[2] != name[2] || pattern[3] != name[3])
   1.302 ++    return FALSE;
   1.303 ++
   1.304 ++  pattern += 4;
   1.305 ++  name += 4;
   1.306 ++  while (*pattern != '*')
   1.307 ++    if (*name++ != *pattern++)
   1.308 ++      return FALSE;
   1.309 ++
   1.310 ++  return TRUE;
   1.311 ++}
   1.312 ++
   1.313 ++/* Specialized, optimized routines for handling different kinds of
   1.314 ++   wildcards */
   1.315 ++
   1.316 ++static void
   1.317 ++walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
   1.318 ++				lang_input_statement_type *file,
   1.319 ++				callback_t callback,
   1.320 ++				void *data)
   1.321 ++{
   1.322 ++  /* We can just do a hash lookup for the section with the right name.
   1.323 ++     But if that lookup discovers more than one section with the name
   1.324 ++     (should be rare), we fall back to the general algorithm because
   1.325 ++     we would otherwise have to sort the sections to make sure they
   1.326 ++     get processed in the bfd's order.  */
   1.327 ++  bfd_boolean multiple_sections_found;
   1.328 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.329 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.330 ++
   1.331 ++  if (multiple_sections_found)
   1.332 ++    walk_wild_section_general (ptr, file, callback, data);
   1.333 ++  else if (s0)
   1.334 ++    walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
   1.335 ++}
   1.336 ++
   1.337 ++static void
   1.338 ++walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
   1.339 ++				lang_input_statement_type *file,
   1.340 ++				callback_t callback,
   1.341 ++				void *data)
   1.342 ++{
   1.343 ++  asection *s;
   1.344 ++  struct wildcard_list *wildsec0 = ptr->handler_data[0];
   1.345 ++
   1.346 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.347 ++    {
   1.348 ++      const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.349 ++      bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
   1.350 ++
   1.351 ++      if (!skip)
   1.352 ++	walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
   1.353 ++    }
   1.354 ++}
   1.355 ++
   1.356 ++static void
   1.357 ++walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
   1.358 ++				lang_input_statement_type *file,
   1.359 ++				callback_t callback,
   1.360 ++				void *data)
   1.361 ++{
   1.362 ++  asection *s;
   1.363 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.364 ++  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   1.365 ++  bfd_boolean multiple_sections_found;
   1.366 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.367 ++
   1.368 ++  if (multiple_sections_found)
   1.369 ++    {
   1.370 ++      walk_wild_section_general (ptr, file, callback, data);
   1.371 ++      return;
   1.372 ++    }
   1.373 ++
   1.374 ++  /* Note that if the section was not found, s0 is NULL and
   1.375 ++     we'll simply never succeed the s == s0 test below.  */
   1.376 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.377 ++    {
   1.378 ++      /* Recall that in this code path, a section cannot satisfy more
   1.379 ++	 than one spec, so if s == s0 then it cannot match
   1.380 ++	 wildspec1.  */
   1.381 ++      if (s == s0)
   1.382 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.383 ++      else
   1.384 ++	{
   1.385 ++	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.386 ++	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   1.387 ++
   1.388 ++	  if (!skip)
   1.389 ++	    walk_wild_consider_section (ptr, file, s, wildsec1, callback,
   1.390 ++					data);
   1.391 ++	}
   1.392 ++    }
   1.393 ++}
   1.394 ++
   1.395 ++static void
   1.396 ++walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
   1.397 ++				lang_input_statement_type *file,
   1.398 ++				callback_t callback,
   1.399 ++				void *data)
   1.400 ++{
   1.401 ++  asection *s;
   1.402 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.403 ++  struct wildcard_list *wildsec1 = ptr->handler_data[1];
   1.404 ++  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   1.405 ++  bfd_boolean multiple_sections_found;
   1.406 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found);
   1.407 ++
   1.408 ++  if (multiple_sections_found)
   1.409 ++    {
   1.410 ++      walk_wild_section_general (ptr, file, callback, data);
   1.411 ++      return;
   1.412 ++    }
   1.413 ++
   1.414 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.415 ++    {
   1.416 ++      if (s == s0)
   1.417 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.418 ++      else
   1.419 ++	{
   1.420 ++	  const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.421 ++	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
   1.422 ++
   1.423 ++	  if (!skip)
   1.424 ++	    walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
   1.425 ++	  else
   1.426 ++	    {
   1.427 ++	      skip = !match_simple_wild (wildsec2->spec.name, sname);
   1.428 ++	      if (!skip)
   1.429 ++		walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   1.430 ++					    data);
   1.431 ++	    }
   1.432 ++	}
   1.433 ++    }
   1.434 ++}
   1.435 ++
   1.436 ++static void
   1.437 ++walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
   1.438 ++				lang_input_statement_type *file,
   1.439 ++				callback_t callback,
   1.440 ++				void *data)
   1.441 ++{
   1.442 ++  asection *s;
   1.443 ++  struct wildcard_list *sec0 = ptr->handler_data[0];
   1.444 ++  struct wildcard_list *sec1 = ptr->handler_data[1];
   1.445 ++  struct wildcard_list *wildsec2 = ptr->handler_data[2];
   1.446 ++  struct wildcard_list *wildsec3 = ptr->handler_data[3];
   1.447 ++  bfd_boolean multiple_sections_found;
   1.448 ++  asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
   1.449 ++
   1.450 ++  if (multiple_sections_found)
   1.451 ++    {
   1.452 ++      walk_wild_section_general (ptr, file, callback, data);
   1.453 ++      return;
   1.454 ++    }
   1.455 ++
   1.456 ++  s1 = find_section (file, sec1, &multiple_sections_found);
   1.457 ++  if (multiple_sections_found)
   1.458 ++    {
   1.459 ++      walk_wild_section_general (ptr, file, callback, data);
   1.460 ++      return;
   1.461 ++    }
   1.462 ++
   1.463 ++  for (s = file->the_bfd->sections; s != NULL; s = s->next)
   1.464 ++    {
   1.465 ++      if (s == s0)
   1.466 ++	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
   1.467 ++      else
   1.468 ++	if (s == s1)
   1.469 ++	  walk_wild_consider_section (ptr, file, s, sec1, callback, data);
   1.470 ++	else
   1.471 ++	  {
   1.472 ++	    const char *sname = bfd_get_section_name (file->the_bfd, s);
   1.473 ++	    bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
   1.474 ++						   sname);
   1.475 ++
   1.476 ++	    if (!skip)
   1.477 ++	      walk_wild_consider_section (ptr, file, s, wildsec2, callback,
   1.478 ++					  data);
   1.479 ++	    else
   1.480 ++	      {
   1.481 ++		skip = !match_simple_wild (wildsec3->spec.name, sname);
   1.482 ++		if (!skip)
   1.483 ++		  walk_wild_consider_section (ptr, file, s, wildsec3,
   1.484 ++					      callback, data);
   1.485 ++	      }
   1.486 ++	  }
   1.487 ++    }
   1.488 ++}
   1.489 ++
   1.490 ++static void
   1.491 ++walk_wild_section (lang_wild_statement_type *ptr,
   1.492 ++		   lang_input_statement_type *file,
   1.493 ++		   callback_t callback,
   1.494 ++		   void *data)
   1.495 ++{
   1.496 ++  if (file->just_syms_flag)
   1.497 ++    return;
   1.498 ++
   1.499 ++  (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
   1.500 ++}
   1.501 ++
   1.502 ++/* Returns TRUE when name1 is a wildcard spec that might match
   1.503 ++   something name2 can match.  We're conservative: we return FALSE
   1.504 ++   only if the prefixes of name1 and name2 are different up to the
   1.505 ++   first wildcard character.  */
   1.506 ++
   1.507 ++static bfd_boolean
   1.508 ++wild_spec_can_overlap (const char *name1, const char *name2)
   1.509 ++{
   1.510 ++  size_t prefix1_len = strcspn (name1, "?*[");
   1.511 ++  size_t prefix2_len = strcspn (name2, "?*[");
   1.512 ++  size_t min_prefix_len;
   1.513 ++
   1.514 ++  /* Note that if there is no wildcard character, then we treat the
   1.515 ++     terminating 0 as part of the prefix.  Thus ".text" won't match
   1.516 ++     ".text." or ".text.*", for example.  */
   1.517 ++  if (name1[prefix1_len] == '\0')
   1.518 ++    prefix1_len++;
   1.519 ++  if (name2[prefix2_len] == '\0')
   1.520 ++    prefix2_len++;
   1.521 ++
   1.522 ++  min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
   1.523 ++
   1.524 ++  return memcmp (name1, name2, min_prefix_len) == 0;
   1.525 ++}
   1.526 ++
   1.527 ++/* Select specialized code to handle various kinds of wildcard
   1.528 ++   statements.  */
   1.529 ++
   1.530 ++static void
   1.531 ++analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
   1.532 ++{
   1.533 ++  int sec_count = 0;
   1.534 ++  int wild_name_count = 0;
   1.535 ++  struct wildcard_list *sec;
   1.536 ++  int signature;
   1.537 ++  int data_counter;
   1.538 ++
   1.539 ++  ptr->walk_wild_section_handler = walk_wild_section_general;
   1.540 ++
   1.541 ++  /* Count how many wildcard_specs there are, and how many of those
   1.542 ++     actually use wildcards in the name.  Also, bail out if any of the
   1.543 ++     wildcard names are NULL. (Can this actually happen?
   1.544 ++     walk_wild_section used to test for it.)  And bail out if any
   1.545 ++     of the wildcards are more complex than a simple string
   1.546 ++     ending in a single '*'.  */
   1.547 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.548 ++    {
   1.549 ++      ++sec_count;
   1.550 ++      if (sec->spec.name == NULL)
   1.551 ++	return;
   1.552 ++      if (wildcardp (sec->spec.name))
   1.553 ++	{
   1.554 ++	  ++wild_name_count;
   1.555 ++	  if (!is_simple_wild (sec->spec.name))
   1.556 ++	    return;
   1.557 ++	}
   1.558 ++    }
   1.559 ++
   1.560 ++  /* The zero-spec case would be easy to optimize but it doesn't
   1.561 ++     happen in practice.  Likewise, more than 4 specs doesn't
   1.562 ++     happen in practice.  */
   1.563 ++  if (sec_count == 0 || sec_count > 4)
   1.564 ++    return;
   1.565 ++
   1.566 ++  /* Check that no two specs can match the same section.  */
   1.567 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.568 ++    {
   1.569 ++      struct wildcard_list *sec2;
   1.570 ++      for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
   1.571 ++	{
   1.572 ++	  if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
   1.573 ++	    return;
   1.574 ++	}
   1.575 ++    }
   1.576 ++
   1.577 ++  signature = (sec_count << 8) + wild_name_count;
   1.578 ++  switch (signature)
   1.579 ++    {
   1.580 ++    case 0x0100:
   1.581 ++      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
   1.582 ++      break;
   1.583 ++    case 0x0101:
   1.584 ++      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
   1.585 ++      break;
   1.586 ++    case 0x0201:
   1.587 ++      ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
   1.588 ++      break;
   1.589 ++    case 0x0302:
   1.590 ++      ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
   1.591 ++      break;
   1.592 ++    case 0x0402:
   1.593 ++      ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
   1.594 ++      break;
   1.595 ++    default:
   1.596 ++      return;
   1.597 ++    }
   1.598 ++
   1.599 ++  /* Now fill the data array with pointers to the specs, first the
   1.600 ++     specs with non-wildcard names, then the specs with wildcard
   1.601 ++     names.  It's OK to process the specs in different order from the
   1.602 ++     given order, because we've already determined that no section
   1.603 ++     will match more than one spec.  */
   1.604 ++  data_counter = 0;
   1.605 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.606 ++    if (!wildcardp (sec->spec.name))
   1.607 ++      ptr->handler_data[data_counter++] = sec;
   1.608 ++  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
   1.609 ++    if (wildcardp (sec->spec.name))
   1.610 ++      ptr->handler_data[data_counter++] = sec;
   1.611 ++}
   1.612 ++
   1.613 + /* Handle a wild statement for a single file F.  */
   1.614 + 
   1.615 + static void
   1.616 +@@ -1175,17 +1559,12 @@
   1.617 + static void
   1.618 + init_os (lang_output_section_statement_type *s)
   1.619 + {
   1.620 +-  lean_section_userdata_type *new;
   1.621 +-
   1.622 +   if (s->bfd_section != NULL)
   1.623 +     return;
   1.624 + 
   1.625 +   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
   1.626 +     einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
   1.627 + 
   1.628 +-  new = stat_alloc (SECTION_USERDATA_SIZE);
   1.629 +-  memset (new, 0, SECTION_USERDATA_SIZE);
   1.630 +-
   1.631 +   s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
   1.632 +   if (s->bfd_section == NULL)
   1.633 +     s->bfd_section = bfd_make_section (output_bfd, s->name);
   1.634 +@@ -1199,7 +1578,14 @@
   1.635 +   /* We initialize an output sections output offset to minus its own
   1.636 +      vma to allow us to output a section through itself.  */
   1.637 +   s->bfd_section->output_offset = 0;
   1.638 +-  get_userdata (s->bfd_section) = new;
   1.639 ++  if (!command_line.reduce_memory_overheads)
   1.640 ++    {
   1.641 ++      fat_section_userdata_type *new
   1.642 ++	= stat_alloc (sizeof (fat_section_userdata_type));
   1.643 ++      memset (new, 0, sizeof (fat_section_userdata_type));
   1.644 ++      get_userdata (s->bfd_section) = new;
   1.645 ++    }
   1.646 ++
   1.647 + 
   1.648 +   /* If there is a base address, make sure that any sections it might
   1.649 +      mention are initialized.  */
   1.650 +@@ -4939,6 +5325,7 @@
   1.651 +   new->section_list = section_list;
   1.652 +   new->keep_sections = keep_sections;
   1.653 +   lang_list_init (&new->children);
   1.654 ++  analyze_walk_wild_section_handler (new);
   1.655 + }
   1.656 + 
   1.657 + void
   1.658 +Index: src/ld/ldlang.h
   1.659 +===================================================================
   1.660 +RCS file: /cvs/src/src/ld/ldlang.h,v
   1.661 +retrieving revision 1.44
   1.662 +retrieving revision 1.45
   1.663 +diff -u -r1.44 -r1.45
   1.664 +--- binutils/ld/ldlang.h.old	3 Mar 2005 11:51:58 -0000	1.44
   1.665 ++++ binutils/ld/ldlang.h	6 Apr 2005 15:33:03 -0000	1.45
   1.666 +@@ -298,7 +298,17 @@
   1.667 +   union lang_statement_union *file;
   1.668 + } lang_afile_asection_pair_statement_type;
   1.669 + 
   1.670 +-typedef struct lang_wild_statement_struct
   1.671 ++typedef struct lang_wild_statement_struct lang_wild_statement_type;
   1.672 ++
   1.673 ++typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
   1.674 ++			    asection *, lang_input_statement_type *, void *);
   1.675 ++
   1.676 ++typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
   1.677 ++					     lang_input_statement_type *,
   1.678 ++					     callback_t callback,
   1.679 ++					     void *data);
   1.680 ++
   1.681 ++struct lang_wild_statement_struct
   1.682 + {
   1.683 +   lang_statement_header_type header;
   1.684 +   const char *filename;
   1.685 +@@ -306,7 +316,10 @@
   1.686 +   struct wildcard_list *section_list;
   1.687 +   bfd_boolean keep_sections;
   1.688 +   lang_statement_list_type children;
   1.689 +-} lang_wild_statement_type;
   1.690 ++
   1.691 ++  walk_wild_section_handler_t walk_wild_section_handler;
   1.692 ++  struct wildcard_list *handler_data[4];
   1.693 ++};
   1.694 + 
   1.695 + typedef struct lang_address_statement_struct
   1.696 + {