patches/binutils/2.15/240-ld-callahan.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Fri Sep 04 17:27:16 2009 +0200 (2009-09-04)
changeset 1512 439a6b292917
parent 745 e445c00d134d
permissions -rw-r--r--
TODO: update

Add TODO list for m4, autoconf, automake and libtool.
Building our own versions would remove burden from the users
who have older versions on their distributions, and are not
ready/able/allowed to upgrade.
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
 {