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