]>
Commit | Line | Data |
---|---|---|
1 | Index: bfd/elflink.c | |
2 | =================================================================== | |
3 | RCS file: /cvs/src/src/bfd/elflink.c,v | |
4 | retrieving revision 1.237 | |
5 | retrieving revision 1.238 | |
6 | diff -u -p -r1.237 -r1.238 | |
7 | --- bfd/elflink.c 30 Oct 2006 23:25:49 -0000 1.237 | |
8 | +++ bfd/elflink.c 17 Nov 2006 13:55:41 -0000 1.238 | |
9 | @@ -7287,8 +7287,8 @@ match_group_member (asection *sec, asect | |
10 | } | |
11 | ||
12 | /* Check if the kept section of a discarded section SEC can be used | |
13 | - to replace it. Return the replacement if it is OK. Otherwise return | |
14 | - NULL. */ | |
15 | + to replace it. Return the replacement if it is OK. Otherwise return | |
16 | + NULL. */ | |
17 | ||
18 | asection * | |
19 | _bfd_elf_check_kept_section (asection *sec, struct bfd_link_info *info) | |
20 | @@ -7298,10 +7298,11 @@ _bfd_elf_check_kept_section (asection *s | |
21 | kept = sec->kept_section; | |
22 | if (kept != NULL) | |
23 | { | |
24 | - if (elf_sec_group (sec) != NULL) | |
25 | + if ((kept->flags & SEC_GROUP) != 0) | |
26 | kept = match_group_member (sec, kept, info); | |
27 | if (kept != NULL && sec->size != kept->size) | |
28 | kept = NULL; | |
29 | + sec->kept_section = kept; | |
30 | } | |
31 | return kept; | |
32 | } | |
33 | @@ -10316,33 +10317,21 @@ _bfd_elf_section_already_linked (bfd *ab | |
34 | const char *name, *p; | |
35 | struct bfd_section_already_linked *l; | |
36 | struct bfd_section_already_linked_hash_entry *already_linked_list; | |
37 | - asection *group; | |
38 | ||
39 | - /* A single member comdat group section may be discarded by a | |
40 | - linkonce section. See below. */ | |
41 | if (sec->output_section == bfd_abs_section_ptr) | |
42 | return; | |
43 | ||
44 | flags = sec->flags; | |
45 | ||
46 | - /* Check if it belongs to a section group. */ | |
47 | - group = elf_sec_group (sec); | |
48 | - | |
49 | - /* Return if it isn't a linkonce section nor a member of a group. A | |
50 | - comdat group section also has SEC_LINK_ONCE set. */ | |
51 | - if ((flags & SEC_LINK_ONCE) == 0 && group == NULL) | |
52 | + /* Return if it isn't a linkonce section. A comdat group section | |
53 | + also has SEC_LINK_ONCE set. */ | |
54 | + if ((flags & SEC_LINK_ONCE) == 0) | |
55 | return; | |
56 | ||
57 | - if (group) | |
58 | - { | |
59 | - /* If this is the member of a single member comdat group, check if | |
60 | - the group should be discarded. */ | |
61 | - if (elf_next_in_group (sec) == sec | |
62 | - && (group->flags & SEC_LINK_ONCE) != 0) | |
63 | - sec = group; | |
64 | - else | |
65 | - return; | |
66 | - } | |
67 | + /* Don't put group member sections on our list of already linked | |
68 | + sections. They are handled as a group via their group section. */ | |
69 | + if (elf_sec_group (sec) != NULL) | |
70 | + return; | |
71 | ||
72 | /* FIXME: When doing a relocatable link, we may have trouble | |
73 | copying relocations in other sections that refer to local symbols | |
74 | @@ -10373,11 +10362,8 @@ _bfd_elf_section_already_linked (bfd *ab | |
75 | ||
76 | for (l = already_linked_list->entry; l != NULL; l = l->next) | |
77 | { | |
78 | - /* We may have 3 different sections on the list: group section, | |
79 | - comdat section and linkonce section. SEC may be a linkonce or | |
80 | - group section. We match a group section with a group section, | |
81 | - a linkonce section with a linkonce section, and ignore comdat | |
82 | - section. */ | |
83 | + /* We may have 2 different types of sections on the list: group | |
84 | + sections and linkonce sections. Match like sections. */ | |
85 | if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) | |
86 | && strcmp (name, l->sec->name) == 0 | |
87 | && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL) | |
88 | @@ -10465,32 +10451,28 @@ _bfd_elf_section_already_linked (bfd *ab | |
89 | } | |
90 | } | |
91 | ||
92 | - if (group) | |
93 | + /* A single member comdat group section may be discarded by a | |
94 | + linkonce section and vice versa. */ | |
95 | + | |
96 | + if ((flags & SEC_GROUP) != 0) | |
97 | { | |
98 | - /* If this is the member of a single member comdat group and the | |
99 | - group hasn't be discarded, we check if it matches a linkonce | |
100 | - section. We only record the discarded comdat group. Otherwise | |
101 | - the undiscarded group will be discarded incorrectly later since | |
102 | - itself has been recorded. */ | |
103 | - for (l = already_linked_list->entry; l != NULL; l = l->next) | |
104 | - if ((l->sec->flags & SEC_GROUP) == 0 | |
105 | - && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL | |
106 | - && bfd_elf_match_symbols_in_sections (l->sec, | |
107 | - elf_next_in_group (sec), | |
108 | - info)) | |
109 | - { | |
110 | - elf_next_in_group (sec)->output_section = bfd_abs_section_ptr; | |
111 | - elf_next_in_group (sec)->kept_section = l->sec; | |
112 | - group->output_section = bfd_abs_section_ptr; | |
113 | - break; | |
114 | - } | |
115 | - if (l == NULL) | |
116 | - return; | |
117 | + asection *first = elf_next_in_group (sec); | |
118 | + | |
119 | + if (first != NULL && elf_next_in_group (first) == first) | |
120 | + /* Check this single member group against linkonce sections. */ | |
121 | + for (l = already_linked_list->entry; l != NULL; l = l->next) | |
122 | + if ((l->sec->flags & SEC_GROUP) == 0 | |
123 | + && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL | |
124 | + && bfd_elf_match_symbols_in_sections (l->sec, first, info)) | |
125 | + { | |
126 | + first->output_section = bfd_abs_section_ptr; | |
127 | + first->kept_section = l->sec; | |
128 | + sec->output_section = bfd_abs_section_ptr; | |
129 | + break; | |
130 | + } | |
131 | } | |
132 | else | |
133 | - /* There is no direct match. But for linkonce section, we should | |
134 | - check if there is a match with comdat group member. We always | |
135 | - record the linkonce section, discarded or not. */ | |
136 | + /* Check this linkonce section against single member groups. */ | |
137 | for (l = already_linked_list->entry; l != NULL; l = l->next) | |
138 | if (l->sec->flags & SEC_GROUP) | |
139 | { | |
140 | @@ -10501,7 +10483,7 @@ _bfd_elf_section_already_linked (bfd *ab | |
141 | && bfd_elf_match_symbols_in_sections (first, sec, info)) | |
142 | { | |
143 | sec->output_section = bfd_abs_section_ptr; | |
144 | - sec->kept_section = l->sec; | |
145 | + sec->kept_section = first; | |
146 | break; | |
147 | } | |
148 | } |