patches/binutils/2.16.1a/130-callahan.patch
author "Benoît Thébaudeau" <benoit.thebaudeau@advansee.com>
Mon Apr 16 15:25:36 2012 +0200 (2012-04-16)
changeset 2941 13e40098fffc
parent 402 197e1b49586e
permissions -rw-r--r--
cc/gcc: update Linaro GCC revisions to 2012.04

Update Linaro GCC with the latest available revisions.

The 4.7 revision is also released, but the infrastructure is not yet ready for
it in CT-NG.

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