1 Signed-off-by: dank@kegel.com
3 See http://weblogs.mozillazine.org/roc/archives/2005/02/optimizing_gnu.html
4 See thread "Re: optimizations for 3x speedup in ld",
5 http://sources.redhat.com/ml/binutils/2005-03/msg00847.html
7 Wildcard section matching enhancement, backported from the binutils CVS tree.
8 Here's the CVS log comment from the original change to ldlang.c:
11 date: 2005/04/06 15:33:02; author: jakub; state: Exp; lines: +438 -51
12 2005-04-06 Jakub Jelinek <jakub@redhat.com>
14 * ldlang.c: Formatting.
15 (walk_wild_consider_section): Remember return value from wildcardp.
16 (is_simple_wild): Use strcspn instead of 2 strpbrk calls and strlen.
17 (wild_spec_can_overlap): Use strcspn instead of strpbrk and strlen.
19 2005-04-06 Robert O'Callahan <rocallahan@novell.com>
21 * ld.h (lean_section_userdata_type): Remove.
22 (fat_section_userdata_type): Remove file field.
23 (SECTION_USERDATA_SIZE): Remove.
24 * ldlang.c (init_os): Eliminate initialization of unused
25 lean_section_userdata_type.
27 * ldlang.h (callback_t, walk_wild_section_handler_t): New
29 (struct lang_wild_statement_struct): Add walk_wild_section_handler
30 and handler_data fields.
31 * ldlang.c (callback_t): Removed.
32 (walk_wild_consider_section, walk_wild_section_general,
33 section_iterator_callback, find_section, is_simple_wild,
34 match_simple_wild, walk_wild_section_specs1_wild0,
35 walk_wild_section_specs1_wild1, walk_wild_section_specs2_wild1,
36 walk_wild_section_specs3_wild2, walk_wild_section_specs4_wild2,
37 wild_spec_can_overlap, analyze_walk_wild_section_handler): New
39 (lang_add_wild): Call analyze_walk_wild_section_handler.
40 (walk_wild_section): Renamed to walk_wild_section_general and
41 created a wrapper function.
42 (section_iterator_callback_data): New typedef.
44 Note that bfd_get_section_by_name_if didn't exist in 2.15, so it was backported
47 --- binutils-2.15/bfd/bfd-in2.h.old 2004-05-17 15:35:56.000000000 -0400
48 +++ binutils-2.15/bfd/bfd-in2.h 2006-02-09 11:54:45.989940000 -0500
49 @@ -1425,6 +1425,10 @@
51 asection *bfd_get_section_by_name (bfd *abfd, const char *name);
53 +asection *bfd_get_section_by_name_if (bfd *abfd, const char *name,
54 + bfd_boolean (*operation) (bfd *, asection *, void *),
55 + void *user_storage);
57 char *bfd_get_unique_section_name
58 (bfd *abfd, const char *templat, int *count);
60 --- binutils-2.15/bfd/section.c.old 2003-12-01 01:33:01.000000000 -0500
61 +++ binutils-2.15/bfd/section.c 2006-01-23 14:16:54.768993000 -0500
66 + bfd_get_section_by_name_if
69 + asection *bfd_get_section_by_name_if
72 + bfd_boolean (*func) (bfd *abfd, asection *sect, void *obj),
76 + Call the provided function @var{func} for each section
77 + attached to the BFD @var{abfd} whose name matches @var{name},
78 + passing @var{obj} as an argument. The function will be called
81 +| func (abfd, the_section, obj);
83 + It returns the first section for which @var{func} returns true,
89 +bfd_get_section_by_name_if (bfd *abfd, const char *name,
90 + bfd_boolean (*operation) (bfd *,
95 + struct section_hash_entry *sh;
98 + sh = section_hash_lookup (&abfd->section_htab, name, FALSE, FALSE);
102 + hash = sh->root.hash;
105 + if ((*operation) (abfd, &sh->section, user_storage))
106 + return &sh->section;
107 + sh = (struct section_hash_entry *) sh->root.next;
109 + while (sh != NULL && sh->root.hash == hash
110 + && strcmp (sh->root.string, name) == 0);
117 bfd_get_unique_section_name
120 --- binutils-2.15/ld/ldlang.c.old 2004-05-17 15:36:16.000000000 -0400
121 +++ binutils-2.15/ld/ldlang.c 2006-01-23 13:40:12.745499000 -0500
123 static void lang_record_phdrs (void);
124 static void lang_do_version_exports_section (void);
126 -typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
127 - asection *, lang_input_statement_type *, void *);
129 /* Exported variables. */
130 lang_output_section_statement_type *abs_output_section;
131 lang_statement_list_type lang_output_section_statement;
132 @@ -138,21 +135,71 @@
134 /* Generic traversal routines for finding matching sections. */
136 +/* Try processing a section against a wildcard. This just calls
137 + the callback unless the filename exclusion list is present
138 + and excludes the file. It's hardly ever present so this
139 + function is very fast. */
142 +walk_wild_consider_section (lang_wild_statement_type *ptr,
143 + lang_input_statement_type *file,
145 + struct wildcard_list *sec,
146 + callback_t callback,
149 + bfd_boolean skip = FALSE;
150 + struct name_list *list_tmp;
152 + /* Don't process sections from files which were
154 + for (list_tmp = sec->spec.exclude_name_list;
156 + list_tmp = list_tmp->next)
158 + bfd_boolean is_wildcard = wildcardp (list_tmp->name);
160 + skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
162 + skip = strcmp (list_tmp->name, file->filename) == 0;
164 + /* If this file is part of an archive, and the archive is
165 + excluded, exclude this file. */
166 + if (! skip && file->the_bfd != NULL
167 + && file->the_bfd->my_archive != NULL
168 + && file->the_bfd->my_archive->filename != NULL)
171 + skip = fnmatch (list_tmp->name,
172 + file->the_bfd->my_archive->filename,
175 + skip = strcmp (list_tmp->name,
176 + file->the_bfd->my_archive->filename) == 0;
184 + (*callback) (ptr, sec, s, file, data);
187 +/* Lowest common denominator routine that can handle everything correctly,
191 -walk_wild_section (lang_wild_statement_type *ptr,
192 - lang_input_statement_type *file,
193 - callback_t callback,
195 +walk_wild_section_general (lang_wild_statement_type *ptr,
196 + lang_input_statement_type *file,
197 + callback_t callback,
202 - if (file->just_syms_flag)
204 + struct wildcard_list *sec;
206 for (s = file->the_bfd->sections; s != NULL; s = s->next)
208 - struct wildcard_list *sec;
210 sec = ptr->section_list;
212 (*callback) (ptr, sec, s, file, data);
216 bfd_boolean skip = FALSE;
217 - struct name_list *list_tmp;
219 - /* Don't process sections from files which were
221 - for (list_tmp = sec->spec.exclude_name_list;
223 - list_tmp = list_tmp->next)
225 - if (wildcardp (list_tmp->name))
226 - skip = fnmatch (list_tmp->name, file->filename, 0) == 0;
228 - skip = strcmp (list_tmp->name, file->filename) == 0;
230 - /* If this file is part of an archive, and the archive is
231 - excluded, exclude this file. */
232 - if (! skip && file->the_bfd != NULL
233 - && file->the_bfd->my_archive != NULL
234 - && file->the_bfd->my_archive->filename != NULL)
236 - if (wildcardp (list_tmp->name))
237 - skip = fnmatch (list_tmp->name,
238 - file->the_bfd->my_archive->filename,
241 - skip = strcmp (list_tmp->name,
242 - file->the_bfd->my_archive->filename) == 0;
249 - if (!skip && sec->spec.name != NULL)
250 + if (sec->spec.name != NULL)
252 const char *sname = bfd_get_section_name (file->the_bfd, s);
254 @@ -203,13 +219,381 @@
258 - (*callback) (ptr, sec, s, file, data);
259 + walk_wild_consider_section (ptr, file, s, sec, callback, data);
266 +/* Routines to find a single section given its name. If there's more
267 + than one section with that name, we report that. */
271 + asection *found_section;
272 + bfd_boolean multiple_sections_found;
273 +} section_iterator_callback_data;
276 +section_iterator_callback (bfd *bfd ATTRIBUTE_UNUSED, asection *s, void *data)
278 + section_iterator_callback_data *d = data;
280 + if (d->found_section != NULL)
282 + d->multiple_sections_found = TRUE;
286 + d->found_section = s;
291 +find_section (lang_input_statement_type *file,
292 + struct wildcard_list *sec,
293 + bfd_boolean *multiple_sections_found)
295 + section_iterator_callback_data cb_data = { NULL, FALSE };
297 + bfd_get_section_by_name_if (file->the_bfd, sec->spec.name,
298 + section_iterator_callback, &cb_data);
299 + *multiple_sections_found = cb_data.multiple_sections_found;
300 + return cb_data.found_section;
303 +/* Code for handling simple wildcards without going through fnmatch,
304 + which can be expensive because of charset translations etc. */
306 +/* A simple wild is a literal string followed by a single '*',
307 + where the literal part is at least 4 characters long. */
310 +is_simple_wild (const char *name)
312 + size_t len = strcspn (name, "*?[");
313 + return len >= 4 && name[len] == '*' && name[len + 1] == '\0';
317 +match_simple_wild (const char *pattern, const char *name)
319 + /* The first four characters of the pattern are guaranteed valid
320 + non-wildcard characters. So we can go faster. */
321 + if (pattern[0] != name[0] || pattern[1] != name[1]
322 + || pattern[2] != name[2] || pattern[3] != name[3])
327 + while (*pattern != '*')
328 + if (*name++ != *pattern++)
334 +/* Specialized, optimized routines for handling different kinds of
338 +walk_wild_section_specs1_wild0 (lang_wild_statement_type *ptr,
339 + lang_input_statement_type *file,
340 + callback_t callback,
343 + /* We can just do a hash lookup for the section with the right name.
344 + But if that lookup discovers more than one section with the name
345 + (should be rare), we fall back to the general algorithm because
346 + we would otherwise have to sort the sections to make sure they
347 + get processed in the bfd's order. */
348 + bfd_boolean multiple_sections_found;
349 + struct wildcard_list *sec0 = ptr->handler_data[0];
350 + asection *s0 = find_section (file, sec0, &multiple_sections_found);
352 + if (multiple_sections_found)
353 + walk_wild_section_general (ptr, file, callback, data);
355 + walk_wild_consider_section (ptr, file, s0, sec0, callback, data);
359 +walk_wild_section_specs1_wild1 (lang_wild_statement_type *ptr,
360 + lang_input_statement_type *file,
361 + callback_t callback,
365 + struct wildcard_list *wildsec0 = ptr->handler_data[0];
367 + for (s = file->the_bfd->sections; s != NULL; s = s->next)
369 + const char *sname = bfd_get_section_name (file->the_bfd, s);
370 + bfd_boolean skip = !match_simple_wild (wildsec0->spec.name, sname);
373 + walk_wild_consider_section (ptr, file, s, wildsec0, callback, data);
378 +walk_wild_section_specs2_wild1 (lang_wild_statement_type *ptr,
379 + lang_input_statement_type *file,
380 + callback_t callback,
384 + struct wildcard_list *sec0 = ptr->handler_data[0];
385 + struct wildcard_list *wildsec1 = ptr->handler_data[1];
386 + bfd_boolean multiple_sections_found;
387 + asection *s0 = find_section (file, sec0, &multiple_sections_found);
389 + if (multiple_sections_found)
391 + walk_wild_section_general (ptr, file, callback, data);
395 + /* Note that if the section was not found, s0 is NULL and
396 + we'll simply never succeed the s == s0 test below. */
397 + for (s = file->the_bfd->sections; s != NULL; s = s->next)
399 + /* Recall that in this code path, a section cannot satisfy more
400 + than one spec, so if s == s0 then it cannot match
403 + walk_wild_consider_section (ptr, file, s, sec0, callback, data);
406 + const char *sname = bfd_get_section_name (file->the_bfd, s);
407 + bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
410 + walk_wild_consider_section (ptr, file, s, wildsec1, callback,
417 +walk_wild_section_specs3_wild2 (lang_wild_statement_type *ptr,
418 + lang_input_statement_type *file,
419 + callback_t callback,
423 + struct wildcard_list *sec0 = ptr->handler_data[0];
424 + struct wildcard_list *wildsec1 = ptr->handler_data[1];
425 + struct wildcard_list *wildsec2 = ptr->handler_data[2];
426 + bfd_boolean multiple_sections_found;
427 + asection *s0 = find_section (file, sec0, &multiple_sections_found);
429 + if (multiple_sections_found)
431 + walk_wild_section_general (ptr, file, callback, data);
435 + for (s = file->the_bfd->sections; s != NULL; s = s->next)
438 + walk_wild_consider_section (ptr, file, s, sec0, callback, data);
441 + const char *sname = bfd_get_section_name (file->the_bfd, s);
442 + bfd_boolean skip = !match_simple_wild (wildsec1->spec.name, sname);
445 + walk_wild_consider_section (ptr, file, s, wildsec1, callback, data);
448 + skip = !match_simple_wild (wildsec2->spec.name, sname);
450 + walk_wild_consider_section (ptr, file, s, wildsec2, callback,
458 +walk_wild_section_specs4_wild2 (lang_wild_statement_type *ptr,
459 + lang_input_statement_type *file,
460 + callback_t callback,
464 + struct wildcard_list *sec0 = ptr->handler_data[0];
465 + struct wildcard_list *sec1 = ptr->handler_data[1];
466 + struct wildcard_list *wildsec2 = ptr->handler_data[2];
467 + struct wildcard_list *wildsec3 = ptr->handler_data[3];
468 + bfd_boolean multiple_sections_found;
469 + asection *s0 = find_section (file, sec0, &multiple_sections_found), *s1;
471 + if (multiple_sections_found)
473 + walk_wild_section_general (ptr, file, callback, data);
477 + s1 = find_section (file, sec1, &multiple_sections_found);
478 + if (multiple_sections_found)
480 + walk_wild_section_general (ptr, file, callback, data);
484 + for (s = file->the_bfd->sections; s != NULL; s = s->next)
487 + walk_wild_consider_section (ptr, file, s, sec0, callback, data);
490 + walk_wild_consider_section (ptr, file, s, sec1, callback, data);
493 + const char *sname = bfd_get_section_name (file->the_bfd, s);
494 + bfd_boolean skip = !match_simple_wild (wildsec2->spec.name,
498 + walk_wild_consider_section (ptr, file, s, wildsec2, callback,
502 + skip = !match_simple_wild (wildsec3->spec.name, sname);
504 + walk_wild_consider_section (ptr, file, s, wildsec3,
512 +walk_wild_section (lang_wild_statement_type *ptr,
513 + lang_input_statement_type *file,
514 + callback_t callback,
517 + if (file->just_syms_flag)
520 + (*ptr->walk_wild_section_handler) (ptr, file, callback, data);
523 +/* Returns TRUE when name1 is a wildcard spec that might match
524 + something name2 can match. We're conservative: we return FALSE
525 + only if the prefixes of name1 and name2 are different up to the
526 + first wildcard character. */
529 +wild_spec_can_overlap (const char *name1, const char *name2)
531 + size_t prefix1_len = strcspn (name1, "?*[");
532 + size_t prefix2_len = strcspn (name2, "?*[");
533 + size_t min_prefix_len;
535 + /* Note that if there is no wildcard character, then we treat the
536 + terminating 0 as part of the prefix. Thus ".text" won't match
537 + ".text." or ".text.*", for example. */
538 + if (name1[prefix1_len] == '\0')
540 + if (name2[prefix2_len] == '\0')
543 + min_prefix_len = prefix1_len < prefix2_len ? prefix1_len : prefix2_len;
545 + return memcmp (name1, name2, min_prefix_len) == 0;
548 +/* Select specialized code to handle various kinds of wildcard
552 +analyze_walk_wild_section_handler (lang_wild_statement_type *ptr)
555 + int wild_name_count = 0;
556 + struct wildcard_list *sec;
560 + ptr->walk_wild_section_handler = walk_wild_section_general;
562 + /* Count how many wildcard_specs there are, and how many of those
563 + actually use wildcards in the name. Also, bail out if any of the
564 + wildcard names are NULL. (Can this actually happen?
565 + walk_wild_section used to test for it.) And bail out if any
566 + of the wildcards are more complex than a simple string
567 + ending in a single '*'. */
568 + for (sec = ptr->section_list; sec != NULL; sec = sec->next)
571 + if (sec->spec.name == NULL)
573 + if (wildcardp (sec->spec.name))
576 + if (!is_simple_wild (sec->spec.name))
581 + /* The zero-spec case would be easy to optimize but it doesn't
582 + happen in practice. Likewise, more than 4 specs doesn't
583 + happen in practice. */
584 + if (sec_count == 0 || sec_count > 4)
587 + /* Check that no two specs can match the same section. */
588 + for (sec = ptr->section_list; sec != NULL; sec = sec->next)
590 + struct wildcard_list *sec2;
591 + for (sec2 = sec->next; sec2 != NULL; sec2 = sec2->next)
593 + if (wild_spec_can_overlap (sec->spec.name, sec2->spec.name))
598 + signature = (sec_count << 8) + wild_name_count;
602 + ptr->walk_wild_section_handler = walk_wild_section_specs1_wild0;
605 + ptr->walk_wild_section_handler = walk_wild_section_specs1_wild1;
608 + ptr->walk_wild_section_handler = walk_wild_section_specs2_wild1;
611 + ptr->walk_wild_section_handler = walk_wild_section_specs3_wild2;
614 + ptr->walk_wild_section_handler = walk_wild_section_specs4_wild2;
620 + /* Now fill the data array with pointers to the specs, first the
621 + specs with non-wildcard names, then the specs with wildcard
622 + names. It's OK to process the specs in different order from the
623 + given order, because we've already determined that no section
624 + will match more than one spec. */
626 + for (sec = ptr->section_list; sec != NULL; sec = sec->next)
627 + if (!wildcardp (sec->spec.name))
628 + ptr->handler_data[data_counter++] = sec;
629 + for (sec = ptr->section_list; sec != NULL; sec = sec->next)
630 + if (wildcardp (sec->spec.name))
631 + ptr->handler_data[data_counter++] = sec;
634 /* Handle a wild statement for a single file F. */
637 @@ -4353,6 +4737,7 @@
638 new->section_list = section_list;
639 new->keep_sections = keep_sections;
640 lang_list_init (&new->children);
641 + analyze_walk_wild_section_handler (new);
645 --- binutils-2.15/ld/ldlang.h.old 2004-05-17 15:36:16.000000000 -0400
646 +++ binutils-2.15/ld/ldlang.h 2006-01-23 13:32:33.653292000 -0500
648 union lang_statement_union *file;
649 } lang_afile_asection_pair_statement_type;
651 -typedef struct lang_wild_statement_struct
652 +typedef struct lang_wild_statement_struct lang_wild_statement_type;
654 +typedef void (*callback_t) (lang_wild_statement_type *, struct wildcard_list *,
655 + asection *, lang_input_statement_type *, void *);
657 +typedef void (*walk_wild_section_handler_t) (lang_wild_statement_type *,
658 + lang_input_statement_type *,
659 + callback_t callback,
662 +struct lang_wild_statement_struct
664 lang_statement_header_type header;
665 const char *filename;
667 struct wildcard_list *section_list;
668 bfd_boolean keep_sections;
669 lang_statement_list_type children;
670 -} lang_wild_statement_type;
672 + walk_wild_section_handler_t walk_wild_section_handler;
673 + struct wildcard_list *handler_data[4];
676 typedef struct lang_address_statement_struct