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