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