Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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