Rev 5199 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5199 | Rev 6324 | ||
---|---|---|---|
1 | /* ldcref.c -- output a cross reference table |
1 | /* ldcref.c -- output a cross reference table |
2 | Copyright 1996-2013 Free Software Foundation, Inc. |
2 | Copyright (C) 1996-2015 Free Software Foundation, Inc. |
3 | Written by Ian Lance Taylor |
3 | Written by Ian Lance Taylor |
4 | 4 | ||
5 | This file is part of the GNU Binutils. |
5 | This file is part of the GNU Binutils. |
6 | 6 | ||
7 | This program is free software; you can redistribute it and/or modify |
7 | This program is free software; you can redistribute it and/or modify |
8 | it under the terms of the GNU General Public License as published by |
8 | it under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 3 of the License, or |
9 | the Free Software Foundation; either version 3 of the License, or |
10 | (at your option) any later version. |
10 | (at your option) any later version. |
11 | 11 | ||
12 | This program is distributed in the hope that it will be useful, |
12 | This program is distributed in the hope that it will be useful, |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | GNU General Public License for more details. |
15 | GNU General Public License for more details. |
16 | 16 | ||
17 | You should have received a copy of the GNU General Public License |
17 | You should have received a copy of the GNU General Public License |
18 | along with this program; if not, write to the Free Software |
18 | along with this program; if not, write to the Free Software |
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
20 | MA 02110-1301, USA. */ |
20 | MA 02110-1301, USA. */ |
21 | 21 | ||
22 | 22 | ||
23 | /* This file holds routines that manage the cross reference table. |
23 | /* This file holds routines that manage the cross reference table. |
24 | The table is used to generate cross reference reports. It is also |
24 | The table is used to generate cross reference reports. It is also |
25 | used to implement the NOCROSSREFS command in the linker script. */ |
25 | used to implement the NOCROSSREFS command in the linker script. */ |
26 | 26 | ||
27 | #include "sysdep.h" |
27 | #include "sysdep.h" |
28 | #include "bfd.h" |
28 | #include "bfd.h" |
29 | #include "bfdlink.h" |
29 | #include "bfdlink.h" |
30 | #include "libiberty.h" |
30 | #include "libiberty.h" |
31 | #include "demangle.h" |
31 | #include "demangle.h" |
32 | #include "objalloc.h" |
32 | #include "objalloc.h" |
33 | 33 | ||
34 | #include "ld.h" |
34 | #include "ld.h" |
35 | #include "ldmain.h" |
35 | #include "ldmain.h" |
36 | #include "ldmisc.h" |
36 | #include "ldmisc.h" |
37 | #include "ldexp.h" |
37 | #include "ldexp.h" |
38 | #include "ldlang.h" |
38 | #include "ldlang.h" |
39 | 39 | ||
40 | /* We keep an instance of this structure for each reference to a |
40 | /* We keep an instance of this structure for each reference to a |
41 | symbol from a given object. */ |
41 | symbol from a given object. */ |
42 | 42 | ||
- | 43 | struct cref_ref |
|
43 | struct cref_ref { |
44 | { |
44 | /* The next reference. */ |
45 | /* The next reference. */ |
45 | struct cref_ref *next; |
46 | struct cref_ref *next; |
46 | /* The object. */ |
47 | /* The object. */ |
47 | bfd *abfd; |
48 | bfd *abfd; |
48 | /* True if the symbol is defined. */ |
49 | /* True if the symbol is defined. */ |
49 | unsigned int def : 1; |
50 | unsigned int def : 1; |
50 | /* True if the symbol is common. */ |
51 | /* True if the symbol is common. */ |
51 | unsigned int common : 1; |
52 | unsigned int common : 1; |
52 | /* True if the symbol is undefined. */ |
53 | /* True if the symbol is undefined. */ |
53 | unsigned int undef : 1; |
54 | unsigned int undef : 1; |
54 | }; |
55 | }; |
55 | 56 | ||
56 | /* We keep a hash table of symbols. Each entry looks like this. */ |
57 | /* We keep a hash table of symbols. Each entry looks like this. */ |
57 | 58 | ||
- | 59 | struct cref_hash_entry |
|
58 | struct cref_hash_entry { |
60 | { |
59 | struct bfd_hash_entry root; |
61 | struct bfd_hash_entry root; |
60 | /* The demangled name. */ |
62 | /* The demangled name. */ |
61 | const char *demangled; |
63 | const char *demangled; |
62 | /* References to and definitions of this symbol. */ |
64 | /* References to and definitions of this symbol. */ |
63 | struct cref_ref *refs; |
65 | struct cref_ref *refs; |
64 | }; |
66 | }; |
65 | 67 | ||
66 | /* This is what the hash table looks like. */ |
68 | /* This is what the hash table looks like. */ |
67 | 69 | ||
- | 70 | struct cref_hash_table |
|
68 | struct cref_hash_table { |
71 | { |
69 | struct bfd_hash_table root; |
72 | struct bfd_hash_table root; |
70 | }; |
73 | }; |
71 | 74 | ||
72 | /* Forward declarations. */ |
75 | /* Forward declarations. */ |
73 | 76 | ||
74 | static void output_one_cref (FILE *, struct cref_hash_entry *); |
77 | static void output_one_cref (FILE *, struct cref_hash_entry *); |
75 | static void check_local_sym_xref (lang_input_statement_type *); |
78 | static void check_local_sym_xref (lang_input_statement_type *); |
76 | static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *); |
79 | static bfd_boolean check_nocrossref (struct cref_hash_entry *, void *); |
77 | static void check_refs (const char *, bfd_boolean, asection *, bfd *, |
80 | static void check_refs (const char *, bfd_boolean, asection *, bfd *, |
78 | struct lang_nocrossrefs *); |
81 | struct lang_nocrossrefs *); |
79 | static void check_reloc_refs (bfd *, asection *, void *); |
82 | static void check_reloc_refs (bfd *, asection *, void *); |
80 | 83 | ||
81 | /* Look up an entry in the cref hash table. */ |
84 | /* Look up an entry in the cref hash table. */ |
82 | 85 | ||
83 | #define cref_hash_lookup(table, string, create, copy) \ |
86 | #define cref_hash_lookup(table, string, create, copy) \ |
84 | ((struct cref_hash_entry *) \ |
87 | ((struct cref_hash_entry *) \ |
85 | bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
88 | bfd_hash_lookup (&(table)->root, (string), (create), (copy))) |
86 | 89 | ||
87 | /* Traverse the cref hash table. */ |
90 | /* Traverse the cref hash table. */ |
88 | 91 | ||
89 | #define cref_hash_traverse(table, func, info) \ |
92 | #define cref_hash_traverse(table, func, info) \ |
90 | (bfd_hash_traverse \ |
93 | (bfd_hash_traverse \ |
91 | (&(table)->root, \ |
94 | (&(table)->root, \ |
92 | (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \ |
95 | (bfd_boolean (*) (struct bfd_hash_entry *, void *)) (func), \ |
93 | (info))) |
96 | (info))) |
94 | 97 | ||
95 | /* The cref hash table. */ |
98 | /* The cref hash table. */ |
96 | 99 | ||
97 | static struct cref_hash_table cref_table; |
100 | static struct cref_hash_table cref_table; |
98 | 101 | ||
99 | /* Whether the cref hash table has been initialized. */ |
102 | /* Whether the cref hash table has been initialized. */ |
100 | 103 | ||
101 | static bfd_boolean cref_initialized; |
104 | static bfd_boolean cref_initialized; |
102 | 105 | ||
103 | /* The number of symbols seen so far. */ |
106 | /* The number of symbols seen so far. */ |
104 | 107 | ||
105 | static size_t cref_symcount; |
108 | static size_t cref_symcount; |
106 | 109 | ||
107 | /* Used to take a snapshot of the cref hash table when starting to |
110 | /* Used to take a snapshot of the cref hash table when starting to |
108 | add syms from an as-needed library. */ |
111 | add syms from an as-needed library. */ |
109 | static struct bfd_hash_entry **old_table; |
112 | static struct bfd_hash_entry **old_table; |
110 | static unsigned int old_size; |
113 | static unsigned int old_size; |
111 | static unsigned int old_count; |
114 | static unsigned int old_count; |
112 | static void *old_tab; |
115 | static void * old_tab; |
113 | static void *alloc_mark; |
116 | static void * alloc_mark; |
114 | static size_t tabsize, entsize, refsize; |
117 | static size_t tabsize, entsize, refsize; |
115 | static size_t old_symcount; |
118 | static size_t old_symcount; |
116 | 119 | ||
117 | /* Create an entry in a cref hash table. */ |
120 | /* Create an entry in a cref hash table. */ |
118 | 121 | ||
119 | static struct bfd_hash_entry * |
122 | static struct bfd_hash_entry * |
120 | cref_hash_newfunc (struct bfd_hash_entry *entry, |
123 | cref_hash_newfunc (struct bfd_hash_entry *entry, |
121 | struct bfd_hash_table *table, |
124 | struct bfd_hash_table *table, |
122 | const char *string) |
125 | const char *string) |
123 | { |
126 | { |
124 | struct cref_hash_entry *ret = (struct cref_hash_entry *) entry; |
127 | struct cref_hash_entry *ret = (struct cref_hash_entry *) entry; |
125 | 128 | ||
126 | /* Allocate the structure if it has not already been allocated by a |
129 | /* Allocate the structure if it has not already been allocated by a |
127 | subclass. */ |
130 | subclass. */ |
128 | if (ret == NULL) |
131 | if (ret == NULL) |
129 | ret = ((struct cref_hash_entry *) |
132 | ret = ((struct cref_hash_entry *) |
130 | bfd_hash_allocate (table, sizeof (struct cref_hash_entry))); |
133 | bfd_hash_allocate (table, sizeof (struct cref_hash_entry))); |
131 | if (ret == NULL) |
134 | if (ret == NULL) |
132 | return NULL; |
135 | return NULL; |
133 | 136 | ||
134 | /* Call the allocation method of the superclass. */ |
137 | /* Call the allocation method of the superclass. */ |
135 | ret = ((struct cref_hash_entry *) |
138 | ret = ((struct cref_hash_entry *) |
136 | bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); |
139 | bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); |
137 | if (ret != NULL) |
140 | if (ret != NULL) |
138 | { |
141 | { |
139 | /* Set local fields. */ |
142 | /* Set local fields. */ |
140 | ret->demangled = NULL; |
143 | ret->demangled = NULL; |
141 | ret->refs = NULL; |
144 | ret->refs = NULL; |
142 | 145 | ||
143 | /* Keep a count of the number of entries created in the hash |
146 | /* Keep a count of the number of entries created in the hash |
144 | table. */ |
147 | table. */ |
145 | ++cref_symcount; |
148 | ++cref_symcount; |
146 | } |
149 | } |
147 | 150 | ||
148 | return &ret->root; |
151 | return &ret->root; |
149 | } |
152 | } |
150 | 153 | ||
151 | /* Add a symbol to the cref hash table. This is called for every |
154 | /* Add a symbol to the cref hash table. This is called for every |
152 | global symbol that is seen during the link. */ |
155 | global symbol that is seen during the link. */ |
153 | 156 | ||
154 | void |
157 | void |
155 | add_cref (const char *name, |
158 | add_cref (const char *name, |
156 | bfd *abfd, |
159 | bfd *abfd, |
157 | asection *section, |
160 | asection *section, |
158 | bfd_vma value ATTRIBUTE_UNUSED) |
161 | bfd_vma value ATTRIBUTE_UNUSED) |
159 | { |
162 | { |
160 | struct cref_hash_entry *h; |
163 | struct cref_hash_entry *h; |
161 | struct cref_ref *r; |
164 | struct cref_ref *r; |
162 | 165 | ||
163 | if (! cref_initialized) |
166 | if (! cref_initialized) |
164 | { |
167 | { |
165 | if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc, |
168 | if (!bfd_hash_table_init (&cref_table.root, cref_hash_newfunc, |
166 | sizeof (struct cref_hash_entry))) |
169 | sizeof (struct cref_hash_entry))) |
167 | einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n")); |
170 | einfo (_("%X%P: bfd_hash_table_init of cref table failed: %E\n")); |
168 | cref_initialized = TRUE; |
171 | cref_initialized = TRUE; |
169 | } |
172 | } |
170 | 173 | ||
171 | h = cref_hash_lookup (&cref_table, name, TRUE, FALSE); |
174 | h = cref_hash_lookup (&cref_table, name, TRUE, FALSE); |
172 | if (h == NULL) |
175 | if (h == NULL) |
173 | einfo (_("%X%P: cref_hash_lookup failed: %E\n")); |
176 | einfo (_("%X%P: cref_hash_lookup failed: %E\n")); |
174 | 177 | ||
175 | for (r = h->refs; r != NULL; r = r->next) |
178 | for (r = h->refs; r != NULL; r = r->next) |
176 | if (r->abfd == abfd) |
179 | if (r->abfd == abfd) |
177 | break; |
180 | break; |
178 | 181 | ||
179 | if (r == NULL) |
182 | if (r == NULL) |
180 | { |
183 | { |
181 | r = (struct cref_ref *) bfd_hash_allocate (&cref_table.root, sizeof *r); |
184 | r = (struct cref_ref *) bfd_hash_allocate (&cref_table.root, sizeof *r); |
182 | if (r == NULL) |
185 | if (r == NULL) |
183 | einfo (_("%X%P: cref alloc failed: %E\n")); |
186 | einfo (_("%X%P: cref alloc failed: %E\n")); |
184 | r->next = h->refs; |
187 | r->next = h->refs; |
185 | h->refs = r; |
188 | h->refs = r; |
186 | r->abfd = abfd; |
189 | r->abfd = abfd; |
187 | r->def = FALSE; |
190 | r->def = FALSE; |
188 | r->common = FALSE; |
191 | r->common = FALSE; |
189 | r->undef = FALSE; |
192 | r->undef = FALSE; |
190 | } |
193 | } |
191 | 194 | ||
192 | if (bfd_is_und_section (section)) |
195 | if (bfd_is_und_section (section)) |
193 | r->undef = TRUE; |
196 | r->undef = TRUE; |
194 | else if (bfd_is_com_section (section)) |
197 | else if (bfd_is_com_section (section)) |
195 | r->common = TRUE; |
198 | r->common = TRUE; |
196 | else |
199 | else |
197 | r->def = TRUE; |
200 | r->def = TRUE; |
198 | } |
201 | } |
199 | 202 | ||
200 | /* Called before loading an as-needed library to take a snapshot of |
203 | /* Called before loading an as-needed library to take a snapshot of |
201 | the cref hash table, and after we have loaded or found that the |
204 | the cref hash table, and after we have loaded or found that the |
202 | library was not needed. */ |
205 | library was not needed. */ |
203 | 206 | ||
204 | bfd_boolean |
207 | bfd_boolean |
205 | handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED, |
208 | handle_asneeded_cref (bfd *abfd ATTRIBUTE_UNUSED, |
206 | enum notice_asneeded_action act) |
209 | enum notice_asneeded_action act) |
207 | { |
210 | { |
208 | unsigned int i; |
211 | unsigned int i; |
209 | 212 | ||
210 | if (!cref_initialized) |
213 | if (!cref_initialized) |
211 | return TRUE; |
214 | return TRUE; |
212 | 215 | ||
213 | if (act == notice_as_needed) |
216 | if (act == notice_as_needed) |
214 | { |
217 | { |
215 | char *old_ent, *old_ref; |
218 | char *old_ent, *old_ref; |
216 | 219 | ||
217 | for (i = 0; i < cref_table.root.size; i++) |
220 | for (i = 0; i < cref_table.root.size; i++) |
218 | { |
221 | { |
219 | struct bfd_hash_entry *p; |
222 | struct bfd_hash_entry *p; |
220 | struct cref_hash_entry *c; |
223 | struct cref_hash_entry *c; |
221 | struct cref_ref *r; |
224 | struct cref_ref *r; |
222 | 225 | ||
223 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
226 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
224 | { |
227 | { |
225 | entsize += cref_table.root.entsize; |
228 | entsize += cref_table.root.entsize; |
226 | c = (struct cref_hash_entry *) p; |
229 | c = (struct cref_hash_entry *) p; |
227 | for (r = c->refs; r != NULL; r = r->next) |
230 | for (r = c->refs; r != NULL; r = r->next) |
228 | refsize += sizeof (struct cref_ref); |
231 | refsize += sizeof (struct cref_ref); |
229 | } |
232 | } |
230 | } |
233 | } |
231 | 234 | ||
232 | tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *); |
235 | tabsize = cref_table.root.size * sizeof (struct bfd_hash_entry *); |
233 | old_tab = xmalloc (tabsize + entsize + refsize); |
236 | old_tab = xmalloc (tabsize + entsize + refsize); |
234 | 237 | ||
235 | alloc_mark = bfd_hash_allocate (&cref_table.root, 1); |
238 | alloc_mark = bfd_hash_allocate (&cref_table.root, 1); |
236 | if (alloc_mark == NULL) |
239 | if (alloc_mark == NULL) |
237 | return FALSE; |
240 | return FALSE; |
238 | 241 | ||
239 | memcpy (old_tab, cref_table.root.table, tabsize); |
242 | memcpy (old_tab, cref_table.root.table, tabsize); |
240 | old_ent = (char *) old_tab + tabsize; |
243 | old_ent = (char *) old_tab + tabsize; |
241 | old_ref = (char *) old_ent + entsize; |
244 | old_ref = (char *) old_ent + entsize; |
242 | old_table = cref_table.root.table; |
245 | old_table = cref_table.root.table; |
243 | old_size = cref_table.root.size; |
246 | old_size = cref_table.root.size; |
244 | old_count = cref_table.root.count; |
247 | old_count = cref_table.root.count; |
245 | old_symcount = cref_symcount; |
248 | old_symcount = cref_symcount; |
246 | 249 | ||
247 | for (i = 0; i < cref_table.root.size; i++) |
250 | for (i = 0; i < cref_table.root.size; i++) |
248 | { |
251 | { |
249 | struct bfd_hash_entry *p; |
252 | struct bfd_hash_entry *p; |
250 | struct cref_hash_entry *c; |
253 | struct cref_hash_entry *c; |
251 | struct cref_ref *r; |
254 | struct cref_ref *r; |
252 | 255 | ||
253 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
256 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
254 | { |
257 | { |
255 | memcpy (old_ent, p, cref_table.root.entsize); |
258 | memcpy (old_ent, p, cref_table.root.entsize); |
256 | old_ent = (char *) old_ent + cref_table.root.entsize; |
259 | old_ent = (char *) old_ent + cref_table.root.entsize; |
257 | c = (struct cref_hash_entry *) p; |
260 | c = (struct cref_hash_entry *) p; |
258 | for (r = c->refs; r != NULL; r = r->next) |
261 | for (r = c->refs; r != NULL; r = r->next) |
259 | { |
262 | { |
260 | memcpy (old_ref, r, sizeof (struct cref_ref)); |
263 | memcpy (old_ref, r, sizeof (struct cref_ref)); |
261 | old_ref = (char *) old_ref + sizeof (struct cref_ref); |
264 | old_ref = (char *) old_ref + sizeof (struct cref_ref); |
262 | } |
265 | } |
263 | } |
266 | } |
264 | } |
267 | } |
265 | return TRUE; |
268 | return TRUE; |
266 | } |
269 | } |
267 | 270 | ||
268 | if (act == notice_not_needed) |
271 | if (act == notice_not_needed) |
269 | { |
272 | { |
270 | char *old_ent, *old_ref; |
273 | char *old_ent, *old_ref; |
271 | 274 | ||
272 | if (old_tab == NULL) |
275 | if (old_tab == NULL) |
273 | { |
276 | { |
274 | /* The only way old_tab can be NULL is if the cref hash table |
277 | /* The only way old_tab can be NULL is if the cref hash table |
275 | had not been initialised when notice_as_needed. */ |
278 | had not been initialised when notice_as_needed. */ |
276 | bfd_hash_table_free (&cref_table.root); |
279 | bfd_hash_table_free (&cref_table.root); |
277 | cref_initialized = FALSE; |
280 | cref_initialized = FALSE; |
278 | return TRUE; |
281 | return TRUE; |
279 | } |
282 | } |
280 | 283 | ||
281 | old_ent = (char *) old_tab + tabsize; |
284 | old_ent = (char *) old_tab + tabsize; |
282 | old_ref = (char *) old_ent + entsize; |
285 | old_ref = (char *) old_ent + entsize; |
283 | cref_table.root.table = old_table; |
286 | cref_table.root.table = old_table; |
284 | cref_table.root.size = old_size; |
287 | cref_table.root.size = old_size; |
285 | cref_table.root.count = old_count; |
288 | cref_table.root.count = old_count; |
286 | memcpy (cref_table.root.table, old_tab, tabsize); |
289 | memcpy (cref_table.root.table, old_tab, tabsize); |
287 | cref_symcount = old_symcount; |
290 | cref_symcount = old_symcount; |
288 | 291 | ||
289 | for (i = 0; i < cref_table.root.size; i++) |
292 | for (i = 0; i < cref_table.root.size; i++) |
290 | { |
293 | { |
291 | struct bfd_hash_entry *p; |
294 | struct bfd_hash_entry *p; |
292 | struct cref_hash_entry *c; |
295 | struct cref_hash_entry *c; |
293 | struct cref_ref *r; |
296 | struct cref_ref *r; |
294 | 297 | ||
295 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
298 | for (p = cref_table.root.table[i]; p != NULL; p = p->next) |
296 | { |
299 | { |
297 | memcpy (p, old_ent, cref_table.root.entsize); |
300 | memcpy (p, old_ent, cref_table.root.entsize); |
298 | old_ent = (char *) old_ent + cref_table.root.entsize; |
301 | old_ent = (char *) old_ent + cref_table.root.entsize; |
299 | c = (struct cref_hash_entry *) p; |
302 | c = (struct cref_hash_entry *) p; |
300 | for (r = c->refs; r != NULL; r = r->next) |
303 | for (r = c->refs; r != NULL; r = r->next) |
301 | { |
304 | { |
302 | memcpy (r, old_ref, sizeof (struct cref_ref)); |
305 | memcpy (r, old_ref, sizeof (struct cref_ref)); |
303 | old_ref = (char *) old_ref + sizeof (struct cref_ref); |
306 | old_ref = (char *) old_ref + sizeof (struct cref_ref); |
304 | } |
307 | } |
305 | } |
308 | } |
306 | } |
309 | } |
307 | 310 | ||
308 | objalloc_free_block ((struct objalloc *) cref_table.root.memory, |
311 | objalloc_free_block ((struct objalloc *) cref_table.root.memory, |
309 | alloc_mark); |
312 | alloc_mark); |
310 | } |
313 | } |
311 | else if (act != notice_needed) |
314 | else if (act != notice_needed) |
312 | return FALSE; |
315 | return FALSE; |
313 | 316 | ||
314 | free (old_tab); |
317 | free (old_tab); |
315 | old_tab = NULL; |
318 | old_tab = NULL; |
316 | return TRUE; |
319 | return TRUE; |
317 | } |
320 | } |
318 | 321 | ||
319 | /* Copy the addresses of the hash table entries into an array. This |
322 | /* Copy the addresses of the hash table entries into an array. This |
320 | is called via cref_hash_traverse. We also fill in the demangled |
323 | is called via cref_hash_traverse. We also fill in the demangled |
321 | name. */ |
324 | name. */ |
322 | 325 | ||
323 | static bfd_boolean |
326 | static bfd_boolean |
324 | cref_fill_array (struct cref_hash_entry *h, void *data) |
327 | cref_fill_array (struct cref_hash_entry *h, void *data) |
325 | { |
328 | { |
326 | struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data; |
329 | struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data; |
327 | 330 | ||
328 | ASSERT (h->demangled == NULL); |
331 | ASSERT (h->demangled == NULL); |
329 | h->demangled = bfd_demangle (link_info.output_bfd, h->root.string, |
332 | h->demangled = bfd_demangle (link_info.output_bfd, h->root.string, |
330 | DMGL_ANSI | DMGL_PARAMS); |
333 | DMGL_ANSI | DMGL_PARAMS); |
331 | if (h->demangled == NULL) |
334 | if (h->demangled == NULL) |
332 | h->demangled = h->root.string; |
335 | h->demangled = h->root.string; |
333 | 336 | ||
334 | **pph = h; |
337 | **pph = h; |
335 | 338 | ||
336 | ++*pph; |
339 | ++*pph; |
337 | 340 | ||
338 | return TRUE; |
341 | return TRUE; |
339 | } |
342 | } |
340 | 343 | ||
341 | /* Sort an array of cref hash table entries by name. */ |
344 | /* Sort an array of cref hash table entries by name. */ |
342 | 345 | ||
343 | static int |
346 | static int |
344 | cref_sort_array (const void *a1, const void *a2) |
347 | cref_sort_array (const void *a1, const void *a2) |
345 | { |
348 | { |
346 | const struct cref_hash_entry * const *p1 = |
349 | const struct cref_hash_entry * const *p1 = |
347 | (const struct cref_hash_entry * const *) a1; |
350 | (const struct cref_hash_entry * const *) a1; |
348 | const struct cref_hash_entry * const *p2 = |
351 | const struct cref_hash_entry * const *p2 = |
349 | (const struct cref_hash_entry * const *) a2; |
352 | (const struct cref_hash_entry * const *) a2; |
- | 353 | ||
350 | 354 | if (demangling) |
|
- | 355 | return strcmp ((*p1)->demangled, (*p2)->demangled); |
|
- | 356 | else |
|
351 | return strcmp ((*p1)->demangled, (*p2)->demangled); |
357 | return strcmp ((*p1)->root.string, (*p2)->root.string); |
352 | } |
358 | } |
353 | 359 | ||
354 | /* Write out the cref table. */ |
360 | /* Write out the cref table. */ |
355 | 361 | ||
356 | #define FILECOL (50) |
362 | #define FILECOL (50) |
357 | 363 | ||
358 | void |
364 | void |
359 | output_cref (FILE *fp) |
365 | output_cref (FILE *fp) |
360 | { |
366 | { |
361 | int len; |
367 | int len; |
362 | struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end; |
368 | struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end; |
363 | const char *msg; |
369 | const char *msg; |
364 | 370 | ||
365 | fprintf (fp, _("\nCross Reference Table\n\n")); |
371 | fprintf (fp, _("\nCross Reference Table\n\n")); |
366 | msg = _("Symbol"); |
372 | msg = _("Symbol"); |
367 | fprintf (fp, "%s", msg); |
373 | fprintf (fp, "%s", msg); |
368 | len = strlen (msg); |
374 | len = strlen (msg); |
369 | while (len < FILECOL) |
375 | while (len < FILECOL) |
370 | { |
376 | { |
371 | putc (' ', fp); |
377 | putc (' ', fp); |
372 | ++len; |
378 | ++len; |
373 | } |
379 | } |
374 | fprintf (fp, _("File\n")); |
380 | fprintf (fp, _("File\n")); |
375 | 381 | ||
376 | if (! cref_initialized) |
382 | if (! cref_initialized) |
377 | { |
383 | { |
378 | fprintf (fp, _("No symbols\n")); |
384 | fprintf (fp, _("No symbols\n")); |
379 | return; |
385 | return; |
380 | } |
386 | } |
381 | 387 | ||
382 | csyms = (struct cref_hash_entry **) xmalloc (cref_symcount * sizeof (*csyms)); |
388 | csyms = (struct cref_hash_entry **) xmalloc (cref_symcount * sizeof (*csyms)); |
383 | 389 | ||
384 | csym_fill = csyms; |
390 | csym_fill = csyms; |
385 | cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill); |
391 | cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill); |
386 | ASSERT ((size_t) (csym_fill - csyms) == cref_symcount); |
392 | ASSERT ((size_t) (csym_fill - csyms) == cref_symcount); |
387 | 393 | ||
388 | qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array); |
394 | qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array); |
389 | 395 | ||
390 | csym_end = csyms + cref_symcount; |
396 | csym_end = csyms + cref_symcount; |
391 | for (csym = csyms; csym < csym_end; csym++) |
397 | for (csym = csyms; csym < csym_end; csym++) |
392 | output_one_cref (fp, *csym); |
398 | output_one_cref (fp, *csym); |
393 | } |
399 | } |
394 | 400 | ||
395 | /* Output one entry in the cross reference table. */ |
401 | /* Output one entry in the cross reference table. */ |
396 | 402 | ||
397 | static void |
403 | static void |
398 | output_one_cref (FILE *fp, struct cref_hash_entry *h) |
404 | output_one_cref (FILE *fp, struct cref_hash_entry *h) |
399 | { |
405 | { |
400 | int len; |
406 | int len; |
401 | struct bfd_link_hash_entry *hl; |
407 | struct bfd_link_hash_entry *hl; |
402 | struct cref_ref *r; |
408 | struct cref_ref *r; |
403 | 409 | ||
404 | hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE, |
410 | hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE, |
405 | FALSE, TRUE); |
411 | FALSE, TRUE); |
406 | if (hl == NULL) |
412 | if (hl == NULL) |
407 | einfo ("%P: symbol `%T' missing from main hash table\n", |
413 | einfo ("%P: symbol `%T' missing from main hash table\n", |
408 | h->root.string); |
414 | h->root.string); |
409 | else |
415 | else |
410 | { |
416 | { |
411 | /* If this symbol is defined in a dynamic object but never |
417 | /* If this symbol is defined in a dynamic object but never |
412 | referenced by a normal object, then don't print it. */ |
418 | referenced by a normal object, then don't print it. */ |
413 | if (hl->type == bfd_link_hash_defined) |
419 | if (hl->type == bfd_link_hash_defined) |
414 | { |
420 | { |
415 | if (hl->u.def.section->output_section == NULL) |
421 | if (hl->u.def.section->output_section == NULL) |
416 | return; |
422 | return; |
417 | if (hl->u.def.section->owner != NULL |
423 | if (hl->u.def.section->owner != NULL |
418 | && (hl->u.def.section->owner->flags & DYNAMIC) != 0) |
424 | && (hl->u.def.section->owner->flags & DYNAMIC) != 0) |
419 | { |
425 | { |
420 | for (r = h->refs; r != NULL; r = r->next) |
426 | for (r = h->refs; r != NULL; r = r->next) |
421 | if ((r->abfd->flags & DYNAMIC) == 0) |
427 | if ((r->abfd->flags & DYNAMIC) == 0) |
422 | break; |
428 | break; |
423 | if (r == NULL) |
429 | if (r == NULL) |
424 | return; |
430 | return; |
425 | } |
431 | } |
426 | } |
432 | } |
427 | } |
433 | } |
- | 434 | ||
- | 435 | if (demangling) |
|
428 | 436 | { |
|
429 | fprintf (fp, "%s ", h->demangled); |
437 | fprintf (fp, "%s ", h->demangled); |
- | 438 | len = strlen (h->demangled) + 1; |
|
- | 439 | } |
|
- | 440 | else |
|
- | 441 | { |
|
- | 442 | fprintf (fp, "%s ", h->root.string); |
|
- | 443 | len = strlen (h->root.string) + 1; |
|
430 | len = strlen (h->demangled) + 1; |
444 | } |
431 | 445 | ||
432 | for (r = h->refs; r != NULL; r = r->next) |
446 | for (r = h->refs; r != NULL; r = r->next) |
433 | { |
447 | { |
434 | if (r->def) |
448 | if (r->def) |
435 | { |
449 | { |
436 | while (len < FILECOL) |
450 | while (len < FILECOL) |
437 | { |
451 | { |
438 | putc (' ', fp); |
452 | putc (' ', fp); |
439 | ++len; |
453 | ++len; |
440 | } |
454 | } |
441 | lfinfo (fp, "%B\n", r->abfd); |
455 | lfinfo (fp, "%B\n", r->abfd); |
442 | len = 0; |
456 | len = 0; |
443 | } |
457 | } |
444 | } |
458 | } |
445 | 459 | ||
446 | for (r = h->refs; r != NULL; r = r->next) |
460 | for (r = h->refs; r != NULL; r = r->next) |
447 | { |
461 | { |
448 | if (r->common) |
462 | if (r->common) |
449 | { |
463 | { |
450 | while (len < FILECOL) |
464 | while (len < FILECOL) |
451 | { |
465 | { |
452 | putc (' ', fp); |
466 | putc (' ', fp); |
453 | ++len; |
467 | ++len; |
454 | } |
468 | } |
455 | lfinfo (fp, "%B\n", r->abfd); |
469 | lfinfo (fp, "%B\n", r->abfd); |
456 | len = 0; |
470 | len = 0; |
457 | } |
471 | } |
458 | } |
472 | } |
459 | 473 | ||
460 | for (r = h->refs; r != NULL; r = r->next) |
474 | for (r = h->refs; r != NULL; r = r->next) |
461 | { |
475 | { |
462 | if (! r->def && ! r->common) |
476 | if (! r->def && ! r->common) |
463 | { |
477 | { |
464 | while (len < FILECOL) |
478 | while (len < FILECOL) |
465 | { |
479 | { |
466 | putc (' ', fp); |
480 | putc (' ', fp); |
467 | ++len; |
481 | ++len; |
468 | } |
482 | } |
469 | lfinfo (fp, "%B\n", r->abfd); |
483 | lfinfo (fp, "%B\n", r->abfd); |
470 | len = 0; |
484 | len = 0; |
471 | } |
485 | } |
472 | } |
486 | } |
473 | 487 | ||
474 | ASSERT (len == 0); |
488 | ASSERT (len == 0); |
475 | } |
489 | } |
476 | 490 | ||
477 | /* Check for prohibited cross references. */ |
491 | /* Check for prohibited cross references. */ |
478 | 492 | ||
479 | void |
493 | void |
480 | check_nocrossrefs (void) |
494 | check_nocrossrefs (void) |
481 | { |
495 | { |
482 | if (! cref_initialized) |
496 | if (! cref_initialized) |
483 | return; |
497 | return; |
484 | 498 | ||
485 | cref_hash_traverse (&cref_table, check_nocrossref, NULL); |
499 | cref_hash_traverse (&cref_table, check_nocrossref, NULL); |
486 | 500 | ||
487 | lang_for_each_file (check_local_sym_xref); |
501 | lang_for_each_file (check_local_sym_xref); |
488 | } |
502 | } |
489 | 503 | ||
490 | /* Check for prohibited cross references to local and section symbols. */ |
504 | /* Check for prohibited cross references to local and section symbols. */ |
491 | 505 | ||
492 | static void |
506 | static void |
493 | check_local_sym_xref (lang_input_statement_type *statement) |
507 | check_local_sym_xref (lang_input_statement_type *statement) |
494 | { |
508 | { |
495 | bfd *abfd; |
509 | bfd *abfd; |
496 | asymbol **syms; |
510 | asymbol **syms; |
497 | 511 | ||
498 | abfd = statement->the_bfd; |
512 | abfd = statement->the_bfd; |
499 | if (abfd == NULL) |
513 | if (abfd == NULL) |
500 | return; |
514 | return; |
501 | 515 | ||
502 | if (!bfd_generic_link_read_symbols (abfd)) |
516 | if (!bfd_generic_link_read_symbols (abfd)) |
503 | einfo (_("%B%F: could not read symbols: %E\n"), abfd); |
517 | einfo (_("%B%F: could not read symbols: %E\n"), abfd); |
504 | 518 | ||
505 | for (syms = bfd_get_outsymbols (abfd); *syms; ++syms) |
519 | for (syms = bfd_get_outsymbols (abfd); *syms; ++syms) |
506 | { |
520 | { |
507 | asymbol *sym = *syms; |
521 | asymbol *sym = *syms; |
508 | if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE)) |
522 | if (sym->flags & (BSF_GLOBAL | BSF_WARNING | BSF_INDIRECT | BSF_FILE)) |
509 | continue; |
523 | continue; |
510 | if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0 |
524 | if ((sym->flags & (BSF_LOCAL | BSF_SECTION_SYM)) != 0 |
511 | && sym->section->output_section != NULL) |
525 | && sym->section->output_section != NULL) |
512 | { |
526 | { |
513 | const char *outsecname, *symname; |
527 | const char *outsecname, *symname; |
514 | struct lang_nocrossrefs *ncrs; |
528 | struct lang_nocrossrefs *ncrs; |
515 | struct lang_nocrossref *ncr; |
529 | struct lang_nocrossref *ncr; |
516 | 530 | ||
517 | outsecname = sym->section->output_section->name; |
531 | outsecname = sym->section->output_section->name; |
518 | symname = NULL; |
532 | symname = NULL; |
519 | if ((sym->flags & BSF_SECTION_SYM) == 0) |
533 | if ((sym->flags & BSF_SECTION_SYM) == 0) |
520 | symname = sym->name; |
534 | symname = sym->name; |
521 | for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next) |
535 | for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next) |
522 | for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next) |
536 | for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next) |
523 | if (strcmp (ncr->name, outsecname) == 0) |
537 | if (strcmp (ncr->name, outsecname) == 0) |
524 | check_refs (symname, FALSE, sym->section, abfd, ncrs); |
538 | check_refs (symname, FALSE, sym->section, abfd, ncrs); |
525 | } |
539 | } |
526 | } |
540 | } |
527 | } |
541 | } |
528 | 542 | ||
529 | /* Check one symbol to see if it is a prohibited cross reference. */ |
543 | /* Check one symbol to see if it is a prohibited cross reference. */ |
530 | 544 | ||
531 | static bfd_boolean |
545 | static bfd_boolean |
532 | check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED) |
546 | check_nocrossref (struct cref_hash_entry *h, void *ignore ATTRIBUTE_UNUSED) |
533 | { |
547 | { |
534 | struct bfd_link_hash_entry *hl; |
548 | struct bfd_link_hash_entry *hl; |
535 | asection *defsec; |
549 | asection *defsec; |
536 | const char *defsecname; |
550 | const char *defsecname; |
537 | struct lang_nocrossrefs *ncrs; |
551 | struct lang_nocrossrefs *ncrs; |
538 | struct lang_nocrossref *ncr; |
552 | struct lang_nocrossref *ncr; |
539 | struct cref_ref *ref; |
553 | struct cref_ref *ref; |
540 | 554 | ||
541 | hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE, |
555 | hl = bfd_link_hash_lookup (link_info.hash, h->root.string, FALSE, |
542 | FALSE, TRUE); |
556 | FALSE, TRUE); |
543 | if (hl == NULL) |
557 | if (hl == NULL) |
544 | { |
558 | { |
545 | einfo (_("%P: symbol `%T' missing from main hash table\n"), |
559 | einfo (_("%P: symbol `%T' missing from main hash table\n"), |
546 | h->root.string); |
560 | h->root.string); |
547 | return TRUE; |
561 | return TRUE; |
548 | } |
562 | } |
549 | 563 | ||
550 | if (hl->type != bfd_link_hash_defined |
564 | if (hl->type != bfd_link_hash_defined |
551 | && hl->type != bfd_link_hash_defweak) |
565 | && hl->type != bfd_link_hash_defweak) |
552 | return TRUE; |
566 | return TRUE; |
553 | 567 | ||
554 | defsec = hl->u.def.section->output_section; |
568 | defsec = hl->u.def.section->output_section; |
555 | if (defsec == NULL) |
569 | if (defsec == NULL) |
556 | return TRUE; |
570 | return TRUE; |
557 | defsecname = bfd_get_section_name (defsec->owner, defsec); |
571 | defsecname = bfd_get_section_name (defsec->owner, defsec); |
558 | 572 | ||
559 | for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next) |
573 | for (ncrs = nocrossref_list; ncrs != NULL; ncrs = ncrs->next) |
560 | for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next) |
574 | for (ncr = ncrs->list; ncr != NULL; ncr = ncr->next) |
561 | if (strcmp (ncr->name, defsecname) == 0) |
575 | if (strcmp (ncr->name, defsecname) == 0) |
562 | for (ref = h->refs; ref != NULL; ref = ref->next) |
576 | for (ref = h->refs; ref != NULL; ref = ref->next) |
563 | check_refs (hl->root.string, TRUE, hl->u.def.section, |
577 | check_refs (hl->root.string, TRUE, hl->u.def.section, |
564 | ref->abfd, ncrs); |
578 | ref->abfd, ncrs); |
565 | 579 | ||
566 | return TRUE; |
580 | return TRUE; |
567 | } |
581 | } |
568 | 582 | ||
569 | /* The struct is used to pass information from check_refs to |
583 | /* The struct is used to pass information from check_refs to |
570 | check_reloc_refs through bfd_map_over_sections. */ |
584 | check_reloc_refs through bfd_map_over_sections. */ |
571 | 585 | ||
572 | struct check_refs_info { |
586 | struct check_refs_info { |
573 | const char *sym_name; |
587 | const char *sym_name; |
574 | asection *defsec; |
588 | asection *defsec; |
575 | struct lang_nocrossrefs *ncrs; |
589 | struct lang_nocrossrefs *ncrs; |
576 | asymbol **asymbols; |
590 | asymbol **asymbols; |
577 | bfd_boolean global; |
591 | bfd_boolean global; |
578 | }; |
592 | }; |
579 | 593 | ||
580 | /* This function is called for each symbol defined in a section which |
594 | /* This function is called for each symbol defined in a section which |
581 | prohibits cross references. We need to look through all references |
595 | prohibits cross references. We need to look through all references |
582 | to this symbol, and ensure that the references are not from |
596 | to this symbol, and ensure that the references are not from |
583 | prohibited sections. */ |
597 | prohibited sections. */ |
584 | 598 | ||
585 | static void |
599 | static void |
586 | check_refs (const char *name, |
600 | check_refs (const char *name, |
587 | bfd_boolean global, |
601 | bfd_boolean global, |
588 | asection *sec, |
602 | asection *sec, |
589 | bfd *abfd, |
603 | bfd *abfd, |
590 | struct lang_nocrossrefs *ncrs) |
604 | struct lang_nocrossrefs *ncrs) |
591 | { |
605 | { |
592 | struct check_refs_info info; |
606 | struct check_refs_info info; |
593 | 607 | ||
594 | /* We need to look through the relocations for this BFD, to see |
608 | /* We need to look through the relocations for this BFD, to see |
595 | if any of the relocations which refer to this symbol are from |
609 | if any of the relocations which refer to this symbol are from |
596 | a prohibited section. Note that we need to do this even for |
610 | a prohibited section. Note that we need to do this even for |
597 | the BFD in which the symbol is defined, since even a single |
611 | the BFD in which the symbol is defined, since even a single |
598 | BFD might contain a prohibited cross reference. */ |
612 | BFD might contain a prohibited cross reference. */ |
599 | 613 | ||
600 | if (!bfd_generic_link_read_symbols (abfd)) |
614 | if (!bfd_generic_link_read_symbols (abfd)) |
601 | einfo (_("%B%F: could not read symbols: %E\n"), abfd); |
615 | einfo (_("%B%F: could not read symbols: %E\n"), abfd); |
602 | 616 | ||
603 | info.sym_name = name; |
617 | info.sym_name = name; |
604 | info.global = global; |
618 | info.global = global; |
605 | info.defsec = sec; |
619 | info.defsec = sec; |
606 | info.ncrs = ncrs; |
620 | info.ncrs = ncrs; |
607 | info.asymbols = bfd_get_outsymbols (abfd); |
621 | info.asymbols = bfd_get_outsymbols (abfd); |
608 | bfd_map_over_sections (abfd, check_reloc_refs, &info); |
622 | bfd_map_over_sections (abfd, check_reloc_refs, &info); |
609 | } |
623 | } |
610 | 624 | ||
611 | /* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol |
625 | /* This is called via bfd_map_over_sections. INFO->SYM_NAME is a symbol |
612 | defined in INFO->DEFSECNAME. If this section maps into any of the |
626 | defined in INFO->DEFSECNAME. If this section maps into any of the |
613 | sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we |
627 | sections listed in INFO->NCRS, other than INFO->DEFSECNAME, then we |
614 | look through the relocations. If any of the relocations are to |
628 | look through the relocations. If any of the relocations are to |
615 | INFO->SYM_NAME, then we report a prohibited cross reference error. */ |
629 | INFO->SYM_NAME, then we report a prohibited cross reference error. */ |
616 | 630 | ||
617 | static void |
631 | static void |
618 | check_reloc_refs (bfd *abfd, asection *sec, void *iarg) |
632 | check_reloc_refs (bfd *abfd, asection *sec, void *iarg) |
619 | { |
633 | { |
620 | struct check_refs_info *info = (struct check_refs_info *) iarg; |
634 | struct check_refs_info *info = (struct check_refs_info *) iarg; |
621 | asection *outsec; |
635 | asection *outsec; |
622 | const char *outsecname; |
636 | const char *outsecname; |
623 | asection *outdefsec; |
637 | asection *outdefsec; |
624 | const char *outdefsecname; |
638 | const char *outdefsecname; |
625 | struct lang_nocrossref *ncr; |
639 | struct lang_nocrossref *ncr; |
626 | const char *symname; |
640 | const char *symname; |
627 | bfd_boolean global; |
641 | bfd_boolean global; |
628 | long relsize; |
642 | long relsize; |
629 | arelent **relpp; |
643 | arelent **relpp; |
630 | long relcount; |
644 | long relcount; |
631 | arelent **p, **pend; |
645 | arelent **p, **pend; |
632 | 646 | ||
633 | outsec = sec->output_section; |
647 | outsec = sec->output_section; |
634 | outsecname = bfd_get_section_name (outsec->owner, outsec); |
648 | outsecname = bfd_get_section_name (outsec->owner, outsec); |
635 | 649 | ||
636 | outdefsec = info->defsec->output_section; |
650 | outdefsec = info->defsec->output_section; |
637 | outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec); |
651 | outdefsecname = bfd_get_section_name (outdefsec->owner, outdefsec); |
638 | 652 | ||
639 | /* The section where the symbol is defined is permitted. */ |
653 | /* The section where the symbol is defined is permitted. */ |
640 | if (strcmp (outsecname, outdefsecname) == 0) |
654 | if (strcmp (outsecname, outdefsecname) == 0) |
641 | return; |
655 | return; |
642 | 656 | ||
643 | for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next) |
657 | for (ncr = info->ncrs->list; ncr != NULL; ncr = ncr->next) |
644 | if (strcmp (outsecname, ncr->name) == 0) |
658 | if (strcmp (outsecname, ncr->name) == 0) |
645 | break; |
659 | break; |
646 | 660 | ||
647 | if (ncr == NULL) |
661 | if (ncr == NULL) |
648 | return; |
662 | return; |
649 | 663 | ||
650 | /* This section is one for which cross references are prohibited. |
664 | /* This section is one for which cross references are prohibited. |
651 | Look through the relocations, and see if any of them are to |
665 | Look through the relocations, and see if any of them are to |
652 | INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations |
666 | INFO->SYM_NAME. If INFO->SYMNAME is NULL, check for relocations |
653 | against the section symbol. If INFO->GLOBAL is TRUE, the |
667 | against the section symbol. If INFO->GLOBAL is TRUE, the |
654 | definition is global, check for relocations against the global |
668 | definition is global, check for relocations against the global |
655 | symbols. Otherwise check for relocations against the local and |
669 | symbols. Otherwise check for relocations against the local and |
656 | section symbols. */ |
670 | section symbols. */ |
657 | 671 | ||
658 | symname = info->sym_name; |
672 | symname = info->sym_name; |
659 | global = info->global; |
673 | global = info->global; |
660 | 674 | ||
661 | relsize = bfd_get_reloc_upper_bound (abfd, sec); |
675 | relsize = bfd_get_reloc_upper_bound (abfd, sec); |
662 | if (relsize < 0) |
676 | if (relsize < 0) |
663 | einfo (_("%B%F: could not read relocs: %E\n"), abfd); |
677 | einfo (_("%B%F: could not read relocs: %E\n"), abfd); |
664 | if (relsize == 0) |
678 | if (relsize == 0) |
665 | return; |
679 | return; |
666 | 680 | ||
667 | relpp = (arelent **) xmalloc (relsize); |
681 | relpp = (arelent **) xmalloc (relsize); |
668 | relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols); |
682 | relcount = bfd_canonicalize_reloc (abfd, sec, relpp, info->asymbols); |
669 | if (relcount < 0) |
683 | if (relcount < 0) |
670 | einfo (_("%B%F: could not read relocs: %E\n"), abfd); |
684 | einfo (_("%B%F: could not read relocs: %E\n"), abfd); |
671 | 685 | ||
672 | p = relpp; |
686 | p = relpp; |
673 | pend = p + relcount; |
687 | pend = p + relcount; |
674 | for (; p < pend && *p != NULL; p++) |
688 | for (; p < pend && *p != NULL; p++) |
675 | { |
689 | { |
676 | arelent *q = *p; |
690 | arelent *q = *p; |
677 | 691 | ||
678 | if (q->sym_ptr_ptr != NULL |
692 | if (q->sym_ptr_ptr != NULL |
679 | && *q->sym_ptr_ptr != NULL |
693 | && *q->sym_ptr_ptr != NULL |
680 | && ((global |
694 | && ((global |
681 | && (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr)) |
695 | && (bfd_is_und_section (bfd_get_section (*q->sym_ptr_ptr)) |
682 | || bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr)) |
696 | || bfd_is_com_section (bfd_get_section (*q->sym_ptr_ptr)) |
683 | || ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL |
697 | || ((*q->sym_ptr_ptr)->flags & (BSF_GLOBAL |
684 | | BSF_WEAK)) != 0)) |
698 | | BSF_WEAK)) != 0)) |
685 | || (!global |
699 | || (!global |
686 | && ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL |
700 | && ((*q->sym_ptr_ptr)->flags & (BSF_LOCAL |
687 | | BSF_SECTION_SYM)) != 0 |
701 | | BSF_SECTION_SYM)) != 0 |
688 | && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)) |
702 | && bfd_get_section (*q->sym_ptr_ptr) == info->defsec)) |
689 | && (symname != NULL |
703 | && (symname != NULL |
690 | ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0 |
704 | ? strcmp (bfd_asymbol_name (*q->sym_ptr_ptr), symname) == 0 |
691 | : ((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0)) |
705 | : ((*q->sym_ptr_ptr)->flags & BSF_SECTION_SYM) != 0)) |
692 | { |
706 | { |
693 | /* We found a reloc for the symbol. The symbol is defined |
707 | /* We found a reloc for the symbol. The symbol is defined |
694 | in OUTSECNAME. This reloc is from a section which is |
708 | in OUTSECNAME. This reloc is from a section which is |
695 | mapped into a section from which references to OUTSECNAME |
709 | mapped into a section from which references to OUTSECNAME |
696 | are prohibited. We must report an error. */ |
710 | are prohibited. We must report an error. */ |
697 | einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"), |
711 | einfo (_("%X%C: prohibited cross reference from %s to `%T' in %s\n"), |
698 | abfd, sec, q->address, outsecname, |
712 | abfd, sec, q->address, outsecname, |
699 | bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname); |
713 | bfd_asymbol_name (*q->sym_ptr_ptr), outdefsecname); |
700 | } |
714 | } |
701 | } |
715 | } |
702 | 716 | ||
703 | free (relpp); |
717 | free (relpp); |
704 | }>>>>>>>>>>> |
718 | }>>>>>>>>>>> |