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