patches/binutils/2.16.1/callahan.patch
author "Yann E. MORIN" <yann.morin.1998@anciens.enib.fr>
Sat Feb 24 11:00:05 2007 +0000 (2007-02-24)
changeset 1 eeea35fbf182
permissions -rw-r--r--
Add the full crosstool-NG sources to the new repository of its own.
You might just say: 'Yeah! crosstool-NG's got its own repo!".
Unfortunately, that's because the previous repo got damaged beyond repair and I had no backup.
That means I'm putting backups in place in the afternoon.
That also means we've lost history... :-(
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
yann@1
    45
Index: src/ld/ld.h
yann@1
    46
===================================================================
yann@1
    47
RCS file: /cvs/src/src/ld/ld.h,v
yann@1
    48
retrieving revision 1.26
yann@1
    49
retrieving revision 1.27
yann@1
    50
diff -u -r1.26 -r1.27
yann@1
    51
--- binutils/ld/ld.h.old	16 Mar 2005 21:52:42 -0000	1.26
yann@1
    52
+++ binutils/ld/ld.h	6 Apr 2005 15:33:02 -0000	1.27
yann@1
    53
@@ -1,6 +1,6 @@
yann@1
    54
 /* ld.h -- general linker header file
yann@1
    55
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
yann@1
    56
-   2001, 2002, 2003, 2004
yann@1
    57
+   2001, 2002, 2003, 2004, 2005
yann@1
    58
    Free Software Foundation, Inc.
yann@1
    59
 
yann@1
    60
    This file is part of GLD, the Gnu Linker.
yann@1
    61
@@ -89,28 +89,15 @@
yann@1
    62
   struct map_symbol_def *next;
yann@1
    63
 };
yann@1
    64
 
yann@1
    65
-/* Extra information we hold on sections */
yann@1
    66
-typedef struct lean_user_section_struct {
yann@1
    67
-  /* For output sections: pointer to the section where this data will go.  */
yann@1
    68
-  struct lang_input_statement_struct *file;
yann@1
    69
-} lean_section_userdata_type;
yann@1
    70
-
yann@1
    71
 /* The initial part of fat_user_section_struct has to be idential with
yann@1
    72
    lean_user_section_struct.  */
yann@1
    73
 typedef struct fat_user_section_struct {
yann@1
    74
-  /* For output sections: pointer to the section where this data will go.  */
yann@1
    75
-  struct lang_input_statement_struct *file;
yann@1
    76
   /* For input sections, when writing a map file: head / tail of a linked
yann@1
    77
      list of hash table entries for symbols defined in this section.  */
yann@1
    78
   struct map_symbol_def *map_symbol_def_head;
yann@1
    79
   struct map_symbol_def **map_symbol_def_tail;
yann@1
    80
 } fat_section_userdata_type;
yann@1
    81
 
yann@1
    82
-#define SECTION_USERDATA_SIZE \
yann@1
    83
- (command_line.reduce_memory_overheads \
yann@1
    84
-  ? sizeof (lean_section_userdata_type) \
yann@1
    85
-  : sizeof (fat_section_userdata_type))
yann@1
    86
-
yann@1
    87
 #define get_userdata(x) ((x)->userdata)
yann@1
    88
 
yann@1
    89
 #define BYTE_SIZE	(1)
yann@1
    90
Index: src/ld/ldlang.c
yann@1
    91
===================================================================
yann@1
    92
RCS file: /cvs/src/src/ld/ldlang.c,v
yann@1
    93
retrieving revision 1.176
yann@1
    94
retrieving revision 1.177
yann@1
    95
diff -u -r1.176 -r1.177
yann@1
    96
--- binutils/ld/ldlang.c.old	18 Mar 2005 13:56:26 -0000	1.176
yann@1
    97
+++ binutils/ld/ldlang.c	6 Apr 2005 15:33:02 -0000	1.177
yann@1
    98
@@ -84,9 +84,6 @@
yann@1
    99
 static void lang_record_phdrs (void);
yann@1
   100
 static void lang_do_version_exports_section (void);
yann@1
   101
 
yann@1
   102
-typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
yann@1
   103
-			    asection *, lang_input_statement_type *, void *);
yann@1
   104
-
yann@1
   105
 /* Exported variables.  */
yann@1
   106
 lang_output_section_statement_type *abs_output_section;
yann@1
   107
 lang_statement_list_type lang_output_section_statement;
yann@1
   108
@@ -155,21 +152,71 @@
yann@1
   109
 
yann@1
   110
 /* Generic traversal routines for finding matching sections.  */
yann@1
   111
 
yann@1
   112
+/* Try processing a section against a wildcard.  This just calls
yann@1
   113
+   the callback unless the filename exclusion list is present
yann@1
   114
+   and excludes the file.  It's hardly ever present so this
yann@1
   115
+   function is very fast.  */
yann@1
   116
+
yann@1
   117
+static void
yann@1
   118
+walk_wild_consider_section (lang_wild_statement_type *ptr,
yann@1
   119
+			    lang_input_statement_type *file,
yann@1
   120
+			    asection *s,
yann@1
   121
+			    struct wildcard_list *sec,
yann@1
   122
+			    callback_t callback,
yann@1
   123
+			    void *data)
yann@1
   124
+{
yann@1
   125
+  bfd_boolean skip = FALSE;
yann@1
   126
+  struct name_list *list_tmp;
yann@1
   127
+
yann@1
   128
+  /* Don't process sections from files which were
yann@1
   129
+     excluded.  */
yann@1
   130
+  for (list_tmp = sec->spec.exclude_name_list;
yann@1
   131
+       list_tmp;
yann@1
   132
+       list_tmp = list_tmp->next)
yann@1
   133
+    {
yann@1
   134
+      bfd_boolean is_wildcard = wildcardp (list_tmp->name);
yann@1
   135
+      if (is_wildcard)
yann@1
   136
+	skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
yann@1
   137
+      else
yann@1
   138
+	skip = strcmp (list_tmp->name, file->filename) == 0;
yann@1
   139
+
yann@1
   140
+      /* If this file is part of an archive, and the archive is
yann@1
   141
+	 excluded, exclude this file.  */
yann@1
   142
+      if (! skip && file->the_bfd != NULL
yann@1
   143
+	  && file->the_bfd->my_archive != NULL
yann@1
   144
+	  && file->the_bfd->my_archive->filename != NULL)
yann@1
   145
+	{
yann@1
   146
+	  if (is_wildcard)
yann@1
   147
+	    skip = fnmatch (list_tmp->name,
yann@1
   148
+			    file->the_bfd->my_archive->filename,
yann@1
   149
+			    0) == 0;
yann@1
   150
+	  else
yann@1
   151
+	    skip = strcmp (list_tmp->name,
yann@1
   152
+			   file->the_bfd->my_archive->filename) == 0;
yann@1
   153
+	}
yann@1
   154
+
yann@1
   155
+      if (skip)
yann@1
   156
+	break;
yann@1
   157
+    }
yann@1
   158
+
yann@1
   159
+  if (!skip)
yann@1
   160
+    (*callback) (ptr, sec, s, file, data);
yann@1
   161
+}
yann@1
   162
+
yann@1
   163
+/* Lowest common denominator routine that can handle everything correctly,
yann@1
   164
+   but slowly.  */
yann@1
   165
+
yann@1
   166
 static void
yann@1
   167
-walk_wild_section (lang_wild_statement_type *ptr,
yann@1
   168
-		   lang_input_statement_type *file,
yann@1
   169
-		   callback_t callback,
yann@1
   170
-		   void *data)
yann@1
   171
+walk_wild_section_general (lang_wild_statement_type *ptr,
yann@1
   172
+			   lang_input_statement_type *file,
yann@1
   173
+			   callback_t callback,
yann@1
   174
+			   void *data)
yann@1
   175
 {
yann@1
   176
   asection *s;
yann@1
   177
-
yann@1
   178
-  if (file->just_syms_flag)
yann@1
   179
-    return;
yann@1
   180
+  struct wildcard_list *sec;
yann@1
   181
 
yann@1
   182
   for (s = file->the_bfd->sections; s != NULL; s = s->next)
yann@1
   183
     {
yann@1
   184
-      struct wildcard_list *sec;
yann@1
   185
-
yann@1
   186
       sec = ptr->section_list;
yann@1
   187
       if (sec == NULL)
yann@1
   188
 	(*callback) (ptr, sec, s, file, data);
yann@1
   189
@@ -177,39 +224,8 @@
yann@1
   190
       while (sec != NULL)
yann@1
   191
 	{
yann@1
   192
 	  bfd_boolean skip = FALSE;
yann@1
   193
-	  struct name_list *list_tmp;
yann@1
   194
 
yann@1
   195
-	  /* Don't process sections from files which were
yann@1
   196
-	     excluded.  */
yann@1
   197
-	  for (list_tmp = sec->spec.exclude_name_list;
yann@1
   198
-	       list_tmp;
yann@1
   199
-	       list_tmp = list_tmp->next)
yann@1
   200
-	    {
yann@1
   201
-	      if (wildcardp (list_tmp->name))
yann@1
   202
-		skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
yann@1
   203
-	      else
yann@1
   204
-		skip = strcmp (list_tmp->name, file->filename) == 0;
yann@1
   205
-
yann@1
   206
-	      /* If this file is part of an archive, and the archive is
yann@1
   207
-		 excluded, exclude this file.  */
yann@1
   208
-	      if (! skip && file->the_bfd != NULL
yann@1
   209
-		  && file->the_bfd->my_archive != NULL
yann@1
   210
-		  && file->the_bfd->my_archive->filename != NULL)
yann@1
   211
-		{
yann@1
   212
-		  if (wildcardp (list_tmp->name))
yann@1
   213
-		    skip = fnmatch (list_tmp->name,
yann@1
   214
-				    file->the_bfd->my_archive->filename,
yann@1
   215
-				    0) == 0;
yann@1
   216
-		  else
yann@1
   217
-		    skip = strcmp (list_tmp->name,
yann@1
   218
-				   file->the_bfd->my_archive->filename) == 0;
yann@1
   219
-		}
yann@1
   220
-
yann@1
   221
-	      if (skip)
yann@1
   222
-		break;
yann@1
   223
-	    }
yann@1
   224
-
yann@1
   225
-	  if (!skip && sec->spec.name != NULL)
yann@1
   226
+	  if (sec->spec.name != NULL)
yann@1
   227
 	    {
yann@1
   228
 	      const char *sname = bfd_get_section_name (file->the_bfd, s);
yann@1
   229
 
yann@1
   230
@@ -220,13 +236,381 @@
yann@1
   231
 	    }
yann@1
   232
 
yann@1
   233
 	  if (!skip)
yann@1
   234
-	    (*callback) (ptr, sec, s, file, data);
yann@1
   235
+	    walk_wild_consider_section (ptr, file, s, sec, callback, data);
yann@1
   236
 
yann@1
   237
 	  sec = sec->next;
yann@1
   238
 	}
yann@1
   239
     }
yann@1
   240
 }
yann@1
   241
 
yann@1
   242
+/* Routines to find a single section given its name.  If there's more
yann@1
   243
+   than one section with that name, we report that.  */
yann@1
   244
+
yann@1
   245
+typedef struct
yann@1
   246
+{
yann@1
   247
+  asection *found_section;
yann@1
   248
+  bfd_boolean multiple_sections_found;
yann@1
   249
+} section_iterator_callback_data;
yann@1
   250
+
yann@1
   251
+static bfd_boolean
yann@1
   252
+section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
yann@1
   253
+{
yann@1
   254
+  section_iterator_callback_data *d = data;
yann@1
   255
+
yann@1
   256
+  if (d->found_section != NULL)
yann@1
   257
+    {
yann@1
   258
+      d->multiple_sections_found = TRUE;
yann@1
   259
+      return TRUE;
yann@1
   260
+    }
yann@1
   261
+
yann@1
   262
+  d->found_section = s;
yann@1
   263
+  return FALSE;
yann@1
   264
+}
yann@1
   265
+
yann@1
   266
+static asection *
yann@1
   267
+find_section (lang_input_statement_type *file,
yann@1
   268
+	      struct wildcard_list *sec,
yann@1
   269
+	      bfd_boolean *multiple_sections_found)
yann@1
   270
+{
yann@1
   271
+  section_iterator_callback_data cb_data = { NULL, FALSE };
yann@1
   272
+
yann@1
   273
+  bfd_get_section_by_name_if (file->the_bfd, sec->spec.name, 
yann@1
   274
+			      section_iterator_callback, &cb_data);
yann@1
   275
+  *multiple_sections_found = cb_data.multiple_sections_found;
yann@1
   276
+  return cb_data.found_section;
yann@1
   277
+}
yann@1
   278
+
yann@1
   279
+/* Code for handling simple wildcards without going through fnmatch,
yann@1
   280
+   which can be expensive because of charset translations etc.  */
yann@1
   281
+
yann@1
   282
+/* A simple wild is a literal string followed by a single '*',
yann@1
   283
+   where the literal part is at least 4 characters long.  */
yann@1
   284
+
yann@1
   285
+static bfd_boolean
yann@1
   286
+is_simple_wild (const char *name)
yann@1
   287
+{
yann@1
   288
+  size_t len = strcspn (name, "*?[");
yann@1
   289
+  return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
yann@1
   290
+}
yann@1
   291
+
yann@1
   292
+static bfd_boolean
yann@1
   293
+match_simple_wild (const char *pattern, const char *name)
yann@1
   294
+{
yann@1
   295
+  /* The first four characters of the pattern are guaranteed valid
yann@1
   296
+     non-wildcard characters.  So we can go faster.  */
yann@1
   297
+  if (pattern[0] != name[0] || pattern[1] != name[1]
yann@1
   298
+      || pattern[2] != name[2] || pattern[3] != name[3])
yann@1
   299
+    return FALSE;
yann@1
   300
+
yann@1
   301
+  pattern += 4;
yann@1
   302
+  name += 4;
yann@1
   303
+  while (*pattern != '*')
yann@1
   304
+    if (*name++ != *pattern++)
yann@1
   305
+      return FALSE;
yann@1
   306
+
yann@1
   307
+  return TRUE;
yann@1
   308
+}
yann@1
   309
+
yann@1
   310
+/* Specialized, optimized routines for handling different kinds of
yann@1
   311
+   wildcards */
yann@1
   312
+
yann@1
   313
+static void
yann@1
   314
+walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
yann@1
   315
+				lang_input_statement_type *file,
yann@1
   316
+				callback_t callback,
yann@1
   317
+				void *data)
yann@1
   318
+{
yann@1
   319
+  /* We can just do a hash lookup for the section with the right name.
yann@1
   320
+     But if that lookup discovers more than one section with the name
yann@1
   321
+     (should be rare), we fall back to the general algorithm because
yann@1
   322
+     we would otherwise have to sort the sections to make sure they
yann@1
   323
+     get processed in the bfd's order.  */
yann@1
   324
+  bfd_boolean multiple_sections_found;
yann@1
   325
+  struct wildcard_list *sec0 = ptr->handler_data[0];
yann@1
   326
+  asection *s0 = find_section (file, sec0, &multiple_sections_found);
yann@1
   327
+
yann@1
   328
+  if (multiple_sections_found)
yann@1
   329
+    walk_wild_section_general (ptr, file, callback, data);
yann@1
   330
+  else if (s0)
yann@1
   331
+    walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
yann@1
   332
+}
yann@1
   333
+
yann@1
   334
+static void
yann@1
   335
+walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
yann@1
   336
+				lang_input_statement_type *file,
yann@1
   337
+				callback_t callback,
yann@1
   338
+				void *data)
yann@1
   339
+{
yann@1
   340
+  asection *s;
yann@1
   341
+  struct wildcard_list *wildsec0 = ptr->handler_data[0];
yann@1
   342
+
yann@1
   343
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
yann@1
   344
+    {
yann@1
   345
+      const char *sname = bfd_get_section_name (file->the_bfd, s);
yann@1
   346
+      bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
yann@1
   347
+
yann@1
   348
+      if (!skip)
yann@1
   349
+	walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
yann@1
   350
+    }
yann@1
   351
+}
yann@1
   352
+
yann@1
   353
+static void
yann@1
   354
+walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
yann@1
   355
+				lang_input_statement_type *file,
yann@1
   356
+				callback_t callback,
yann@1
   357
+				void *data)
yann@1
   358
+{
yann@1
   359
+  asection *s;
yann@1
   360
+  struct wildcard_list *sec0 = ptr->handler_data[0];
yann@1
   361
+  struct wildcard_list *wildsec1 = ptr->handler_data[1];
yann@1
   362
+  bfd_boolean multiple_sections_found;
yann@1
   363
+  asection *s0 = find_section (file, sec0, &multiple_sections_found);
yann@1
   364
+
yann@1
   365
+  if (multiple_sections_found)
yann@1
   366
+    {
yann@1
   367
+      walk_wild_section_general (ptr, file, callback, data);
yann@1
   368
+      return;
yann@1
   369
+    }
yann@1
   370
+
yann@1
   371
+  /* Note that if the section was not found, s0 is NULL and
yann@1
   372
+     we'll simply never succeed the s == s0 test below.  */
yann@1
   373
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
yann@1
   374
+    {
yann@1
   375
+      /* Recall that in this code path, a section cannot satisfy more
yann@1
   376
+	 than one spec, so if s == s0 then it cannot match
yann@1
   377
+	 wildspec1.  */
yann@1
   378
+      if (s == s0)
yann@1
   379
+	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
yann@1
   380
+      else
yann@1
   381
+	{
yann@1
   382
+	  const char *sname = bfd_get_section_name (file->the_bfd, s);
yann@1
   383
+	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
yann@1
   384
+
yann@1
   385
+	  if (!skip)
yann@1
   386
+	    walk_wild_consider_section (ptr, file, s, wildsec1, callback,
yann@1
   387
+					data);
yann@1
   388
+	}
yann@1
   389
+    }
yann@1
   390
+}
yann@1
   391
+
yann@1
   392
+static void
yann@1
   393
+walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
yann@1
   394
+				lang_input_statement_type *file,
yann@1
   395
+				callback_t callback,
yann@1
   396
+				void *data)
yann@1
   397
+{
yann@1
   398
+  asection *s;
yann@1
   399
+  struct wildcard_list *sec0 = ptr->handler_data[0];
yann@1
   400
+  struct wildcard_list *wildsec1 = ptr->handler_data[1];
yann@1
   401
+  struct wildcard_list *wildsec2 = ptr->handler_data[2];
yann@1
   402
+  bfd_boolean multiple_sections_found;
yann@1
   403
+  asection *s0 = find_section (file, sec0, &multiple_sections_found);
yann@1
   404
+
yann@1
   405
+  if (multiple_sections_found)
yann@1
   406
+    {
yann@1
   407
+      walk_wild_section_general (ptr, file, callback, data);
yann@1
   408
+      return;
yann@1
   409
+    }
yann@1
   410
+
yann@1
   411
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
yann@1
   412
+    {
yann@1
   413
+      if (s == s0)
yann@1
   414
+	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
yann@1
   415
+      else
yann@1
   416
+	{
yann@1
   417
+	  const char *sname = bfd_get_section_name (file->the_bfd, s);
yann@1
   418
+	  bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
yann@1
   419
+
yann@1
   420
+	  if (!skip)
yann@1
   421
+	    walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
yann@1
   422
+	  else
yann@1
   423
+	    {
yann@1
   424
+	      skip = !match_simple_wild (wildsec2->spec.name, sname);
yann@1
   425
+	      if (!skip)
yann@1
   426
+		walk_wild_consider_section (ptr, file, s, wildsec2, callback,
yann@1
   427
+					    data);
yann@1
   428
+	    }
yann@1
   429
+	}
yann@1
   430
+    }
yann@1
   431
+}
yann@1
   432
+
yann@1
   433
+static void
yann@1
   434
+walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
yann@1
   435
+				lang_input_statement_type *file,
yann@1
   436
+				callback_t callback,
yann@1
   437
+				void *data)
yann@1
   438
+{
yann@1
   439
+  asection *s;
yann@1
   440
+  struct wildcard_list *sec0 = ptr->handler_data[0];
yann@1
   441
+  struct wildcard_list *sec1 = ptr->handler_data[1];
yann@1
   442
+  struct wildcard_list *wildsec2 = ptr->handler_data[2];
yann@1
   443
+  struct wildcard_list *wildsec3 = ptr->handler_data[3];
yann@1
   444
+  bfd_boolean multiple_sections_found;
yann@1
   445
+  asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
yann@1
   446
+
yann@1
   447
+  if (multiple_sections_found)
yann@1
   448
+    {
yann@1
   449
+      walk_wild_section_general (ptr, file, callback, data);
yann@1
   450
+      return;
yann@1
   451
+    }
yann@1
   452
+
yann@1
   453
+  s1 = find_section (file, sec1, &multiple_sections_found);
yann@1
   454
+  if (multiple_sections_found)
yann@1
   455
+    {
yann@1
   456
+      walk_wild_section_general (ptr, file, callback, data);
yann@1
   457
+      return;
yann@1
   458
+    }
yann@1
   459
+
yann@1
   460
+  for (s = file->the_bfd->sections; s != NULL; s = s->next)
yann@1
   461
+    {
yann@1
   462
+      if (s == s0)
yann@1
   463
+	walk_wild_consider_section (ptr, file, s, sec0, callback, data);
yann@1
   464
+      else
yann@1
   465
+	if (s == s1)
yann@1
   466
+	  walk_wild_consider_section (ptr, file, s, sec1, callback, data);
yann@1
   467
+	else
yann@1
   468
+	  {
yann@1
   469
+	    const char *sname = bfd_get_section_name (file->the_bfd, s);
yann@1
   470
+	    bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
yann@1
   471
+						   sname);
yann@1
   472
+
yann@1
   473
+	    if (!skip)
yann@1
   474
+	      walk_wild_consider_section (ptr, file, s, wildsec2, callback,
yann@1
   475
+					  data);
yann@1
   476
+	    else
yann@1
   477
+	      {
yann@1
   478
+		skip = !match_simple_wild (wildsec3->spec.name, sname);
yann@1
   479
+		if (!skip)
yann@1
   480
+		  walk_wild_consider_section (ptr, file, s, wildsec3,
yann@1
   481
+					      callback, data);
yann@1
   482
+	      }
yann@1
   483
+	  }
yann@1
   484
+    }
yann@1
   485
+}
yann@1
   486
+
yann@1
   487
+static void
yann@1
   488
+walk_wild_section (lang_wild_statement_type *ptr,
yann@1
   489
+		   lang_input_statement_type *file,
yann@1
   490
+		   callback_t callback,
yann@1
   491
+		   void *data)
yann@1
   492
+{
yann@1
   493
+  if (file->just_syms_flag)
yann@1
   494
+    return;
yann@1
   495
+
yann@1
   496
+  (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
yann@1
   497
+}
yann@1
   498
+
yann@1
   499
+/* Returns TRUE when name1 is a wildcard spec that might match
yann@1
   500
+   something name2 can match.  We're conservative: we return FALSE
yann@1
   501
+   only if the prefixes of name1 and name2 are different up to the
yann@1
   502
+   first wildcard character.  */
yann@1
   503
+
yann@1
   504
+static bfd_boolean
yann@1
   505
+wild_spec_can_overlap (const char *name1, const char *name2)
yann@1
   506
+{
yann@1
   507
+  size_t prefix1_len = strcspn (name1, "?*[");
yann@1
   508
+  size_t prefix2_len = strcspn (name2, "?*[");
yann@1
   509
+  size_t min_prefix_len;
yann@1
   510
+
yann@1
   511
+  /* Note that if there is no wildcard character, then we treat the
yann@1
   512
+     terminating 0 as part of the prefix.  Thus ".text" won't match
yann@1
   513
+     ".text." or ".text.*", for example.  */
yann@1
   514
+  if (name1[prefix1_len] == '\0')
yann@1
   515
+    prefix1_len++;
yann@1
   516
+  if (name2[prefix2_len] == '\0')
yann@1
   517
+    prefix2_len++;
yann@1
   518
+
yann@1
   519
+  min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
yann@1
   520
+
yann@1
   521
+  return memcmp (name1, name2, min_prefix_len) == 0;
yann@1
   522
+}
yann@1
   523
+
yann@1
   524
+/* Select specialized code to handle various kinds of wildcard
yann@1
   525
+   statements.  */
yann@1
   526
+
yann@1
   527
+static void
yann@1
   528
+analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
yann@1
   529
+{
yann@1
   530
+  int sec_count = 0;
yann@1
   531
+  int wild_name_count = 0;
yann@1
   532
+  struct wildcard_list *sec;
yann@1
   533
+  int signature;
yann@1
   534
+  int data_counter;
yann@1
   535
+
yann@1
   536
+  ptr->walk_wild_section_handler = walk_wild_section_general;
yann@1
   537
+
yann@1
   538
+  /* Count how many wildcard_specs there are, and how many of those
yann@1
   539
+     actually use wildcards in the name.  Also, bail out if any of the
yann@1
   540
+     wildcard names are NULL. (Can this actually happen?
yann@1
   541
+     walk_wild_section used to test for it.)  And bail out if any
yann@1
   542
+     of the wildcards are more complex than a simple string
yann@1
   543
+     ending in a single '*'.  */
yann@1
   544
+  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
yann@1
   545
+    {
yann@1
   546
+      ++sec_count;
yann@1
   547
+      if (sec->spec.name == NULL)
yann@1
   548
+	return;
yann@1
   549
+      if (wildcardp (sec->spec.name))
yann@1
   550
+	{
yann@1
   551
+	  ++wild_name_count;
yann@1
   552
+	  if (!is_simple_wild (sec->spec.name))
yann@1
   553
+	    return;
yann@1
   554
+	}
yann@1
   555
+    }
yann@1
   556
+
yann@1
   557
+  /* The zero-spec case would be easy to optimize but it doesn't
yann@1
   558
+     happen in practice.  Likewise, more than 4 specs doesn't
yann@1
   559
+     happen in practice.  */
yann@1
   560
+  if (sec_count == 0 || sec_count > 4)
yann@1
   561
+    return;
yann@1
   562
+
yann@1
   563
+  /* Check that no two specs can match the same section.  */
yann@1
   564
+  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
yann@1
   565
+    {
yann@1
   566
+      struct wildcard_list *sec2;
yann@1
   567
+      for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
yann@1
   568
+	{
yann@1
   569
+	  if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
yann@1
   570
+	    return;
yann@1
   571
+	}
yann@1
   572
+    }
yann@1
   573
+
yann@1
   574
+  signature = (sec_count << 8) + wild_name_count;
yann@1
   575
+  switch (signature)
yann@1
   576
+    {
yann@1
   577
+    case 0x0100:
yann@1
   578
+      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
yann@1
   579
+      break;
yann@1
   580
+    case 0x0101:
yann@1
   581
+      ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
yann@1
   582
+      break;
yann@1
   583
+    case 0x0201:
yann@1
   584
+      ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
yann@1
   585
+      break;
yann@1
   586
+    case 0x0302:
yann@1
   587
+      ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
yann@1
   588
+      break;
yann@1
   589
+    case 0x0402:
yann@1
   590
+      ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
yann@1
   591
+      break;
yann@1
   592
+    default:
yann@1
   593
+      return;
yann@1
   594
+    }
yann@1
   595
+
yann@1
   596
+  /* Now fill the data array with pointers to the specs, first the
yann@1
   597
+     specs with non-wildcard names, then the specs with wildcard
yann@1
   598
+     names.  It's OK to process the specs in different order from the
yann@1
   599
+     given order, because we've already determined that no section
yann@1
   600
+     will match more than one spec.  */
yann@1
   601
+  data_counter = 0;
yann@1
   602
+  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
yann@1
   603
+    if (!wildcardp (sec->spec.name))
yann@1
   604
+      ptr->handler_data[data_counter++] = sec;
yann@1
   605
+  for (sec = ptr->section_list; sec != NULL; sec = sec->next)
yann@1
   606
+    if (wildcardp (sec->spec.name))
yann@1
   607
+      ptr->handler_data[data_counter++] = sec;
yann@1
   608
+}
yann@1
   609
+
yann@1
   610
 /* Handle a wild statement for a single file F.  */
yann@1
   611
 
yann@1
   612
 static void
yann@1
   613
@@ -1175,17 +1559,12 @@
yann@1
   614
 static void
yann@1
   615
 init_os (lang_output_section_statement_type *s)
yann@1
   616
 {
yann@1
   617
-  lean_section_userdata_type *new;
yann@1
   618
-
yann@1
   619
   if (s->bfd_section != NULL)
yann@1
   620
     return;
yann@1
   621
 
yann@1
   622
   if (strcmp (s->name, DISCARD_SECTION_NAME) == 0)
yann@1
   623
     einfo (_("%P%F: Illegal use of `%s' section\n"), DISCARD_SECTION_NAME);
yann@1
   624
 
yann@1
   625
-  new = stat_alloc (SECTION_USERDATA_SIZE);
yann@1
   626
-  memset (new, 0, SECTION_USERDATA_SIZE);
yann@1
   627
-
yann@1
   628
   s->bfd_section = bfd_get_section_by_name (output_bfd, s->name);
yann@1
   629
   if (s->bfd_section == NULL)
yann@1
   630
     s->bfd_section = bfd_make_section (output_bfd, s->name);
yann@1
   631
@@ -1199,7 +1578,14 @@
yann@1
   632
   /* We initialize an output sections output offset to minus its own
yann@1
   633
      vma to allow us to output a section through itself.  */
yann@1
   634
   s->bfd_section->output_offset = 0;
yann@1
   635
-  get_userdata (s->bfd_section) = new;
yann@1
   636
+  if (!command_line.reduce_memory_overheads)
yann@1
   637
+    {
yann@1
   638
+      fat_section_userdata_type *new
yann@1
   639
+	= stat_alloc (sizeof (fat_section_userdata_type));
yann@1
   640
+      memset (new, 0, sizeof (fat_section_userdata_type));
yann@1
   641
+      get_userdata (s->bfd_section) = new;
yann@1
   642
+    }
yann@1
   643
+
yann@1
   644
 
yann@1
   645
   /* If there is a base address, make sure that any sections it might
yann@1
   646
      mention are initialized.  */
yann@1
   647
@@ -4939,6 +5325,7 @@
yann@1
   648
   new->section_list = section_list;
yann@1
   649
   new->keep_sections = keep_sections;
yann@1
   650
   lang_list_init (&new->children);
yann@1
   651
+  analyze_walk_wild_section_handler (new);
yann@1
   652
 }
yann@1
   653
 
yann@1
   654
 void
yann@1
   655
Index: src/ld/ldlang.h
yann@1
   656
===================================================================
yann@1
   657
RCS file: /cvs/src/src/ld/ldlang.h,v
yann@1
   658
retrieving revision 1.44
yann@1
   659
retrieving revision 1.45
yann@1
   660
diff -u -r1.44 -r1.45
yann@1
   661
--- binutils/ld/ldlang.h.old	3 Mar 2005 11:51:58 -0000	1.44
yann@1
   662
+++ binutils/ld/ldlang.h	6 Apr 2005 15:33:03 -0000	1.45
yann@1
   663
@@ -298,7 +298,17 @@
yann@1
   664
   union lang_statement_union *file;
yann@1
   665
 } lang_afile_asection_pair_statement_type;
yann@1
   666
 
yann@1
   667
-typedef struct lang_wild_statement_struct
yann@1
   668
+typedef struct lang_wild_statement_struct lang_wild_statement_type;
yann@1
   669
+
yann@1
   670
+typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
yann@1
   671
+			    asection *, lang_input_statement_type *, void *);
yann@1
   672
+
yann@1
   673
+typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
yann@1
   674
+					     lang_input_statement_type *,
yann@1
   675
+					     callback_t callback,
yann@1
   676
+					     void *data);
yann@1
   677
+
yann@1
   678
+struct lang_wild_statement_struct
yann@1
   679
 {
yann@1
   680
   lang_statement_header_type header;
yann@1
   681
   const char *filename;
yann@1
   682
@@ -306,7 +316,10 @@
yann@1
   683
   struct wildcard_list *section_list;
yann@1
   684
   bfd_boolean keep_sections;
yann@1
   685
   lang_statement_list_type children;
yann@1
   686
-} lang_wild_statement_type;
yann@1
   687
+
yann@1
   688
+  walk_wild_section_handler_t walk_wild_section_handler;
yann@1
   689
+  struct wildcard_list *handler_data[4];
yann@1
   690
+};
yann@1
   691
 
yann@1
   692
 typedef struct lang_address_statement_struct
yann@1
   693
 {