Subversion Repositories Kolibri OS

Rev

Rev 5199 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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