]>
Commit | Line | Data |
---|---|---|
52cb69e7 AM |
1 | 2005-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 | ||
8 | 2005-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 | { |