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