Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / gnu / usr.bin / ld / warnings.c
1 /*-
2  * This code is derived from software copyrighted by the Free Software
3  * Foundation.
4  *
5  * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6  *
7  * Modified 1993 by Paul Kranenburg, Erasmus University
8  */
9
10 /* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
11
12 /* Linker `ld' for GNU
13    Copyright (C) 1988 Free Software Foundation, Inc.
14
15    This program is free software; you can redistribute it and/or modify
16    it under the terms of the GNU General Public License as published by
17    the Free Software Foundation; either version 1, or (at your option)
18    any later version.
19
20    This program is distributed in the hope that it will be useful,
21    but WITHOUT ANY WARRANTY; without even the implied warranty of
22    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23    GNU General Public License for more details.
24
25    You should have received a copy of the GNU General Public License
26    along with this program; if not, write to the Free Software
27    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
28
29 /* Written by Richard Stallman with some help from Eric Albert.
30    Set, indirect, and warning symbol features added by Randy Smith. */
31
32 /*
33  * $FreeBSD: src/gnu/usr.bin/ld/warnings.c,v 1.18 1999/08/27 23:36:02 peter Exp $
34  * $DragonFly: src/gnu/usr.bin/ld/Attic/warnings.c,v 1.2 2003/06/17 04:25:46 dillon Exp $
35  */
36
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/file.h>
41 #include <sys/time.h>
42 #include <sys/errno.h>
43 #include <err.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <fcntl.h>
47 #include <ar.h>
48 #include <ranlib.h>
49 #include <a.out.h>
50 #include <stab.h>
51 #include <string.h>
52 #if __STDC__
53 #include <stdarg.h>
54 #else
55 #include <varargs.h>
56 #endif
57
58 #include "ld.h"
59 #include "dynamic.h"
60
61 static int reported_undefineds;
62
63 #ifdef DEMANGLE_CPLUSPLUS
64 #include "demangle.h"
65
66 char *demangle(name)
67      char *name;
68 {
69   static char* saved_result = NULL;
70
71   if (saved_result)
72     free (saved_result);
73
74   saved_result = cplus_demangle (name[0] == '_' ? name + 1 : name, DMGL_PARAMS | DMGL_ANSI);
75
76   if (saved_result)
77     return saved_result;
78   else
79     return name;
80 }
81 #endif
82
83 /*
84  * Print the filename of ENTRY on OUTFILE (a stdio stream),
85  * and then a newline.
86  */
87
88 void
89 prline_file_name (entry, outfile)
90      struct file_entry *entry;
91      FILE *outfile;
92 {
93         print_file_name (entry, outfile);
94         fprintf (outfile, "\n");
95 }
96
97 /*
98  * Print the filename of ENTRY on OUTFILE (a stdio stream).
99  */
100
101 void
102 print_file_name (entry, outfile)
103      struct file_entry *entry;
104      FILE *outfile;
105 {
106         if (entry == NULL) {
107                 fprintf (outfile, "NULL");
108         }
109
110         if (entry->superfile) {
111                 print_file_name (entry->superfile, outfile);
112                 fprintf (outfile, "(%s)", entry->filename);
113         } else
114                 fprintf (outfile, "%s", entry->filename);
115 }
116
117 /*
118  * Return the filename of entry as a string (malloc'd for the purpose)
119  */
120
121 char *
122 get_file_name (entry)
123      struct file_entry *entry;
124 {
125         char *result, *supfile;
126
127         if (entry == NULL) {
128                 return (char *)strdup("NULL");
129         }
130
131         if (entry->superfile) {
132                 supfile = get_file_name(entry->superfile);
133                 result = (char *)
134                         xmalloc(strlen(supfile) + strlen(entry->filename) + 3);
135                 (void)sprintf(result, "%s(%s)", supfile, entry->filename);
136                 free(supfile);
137
138         } else {
139                 result = (char *)xmalloc(strlen(entry->filename) + 1);
140                 strcpy(result, entry->filename);
141         }
142         return result;
143 }
144
145 /* Print a complete or partial map of the output file. */
146
147 static void     describe_file_sections __P((struct file_entry *, FILE *));
148 static void     list_file_locals __P((struct file_entry *, FILE *));
149
150 void
151 print_symbols(outfile)
152         FILE           *outfile;
153 {
154         fprintf(outfile, "\nFiles:\n\n");
155         each_file(describe_file_sections, (void *)outfile);
156
157         fprintf(outfile, "\nGlobal symbols:\n\n");
158         FOR_EACH_SYMBOL(i, sp) {
159                 fprintf(outfile, "  %s: ", demangle(sp->name));
160                 if (!(sp->flags & GS_REFERENCED))
161                         fprintf(outfile, "unreferenced");
162                 else if (sp->so_defined)
163                         fprintf(outfile, "sodefined");
164                 else if (!sp->defined)
165                         fprintf(outfile, "undefined");
166                 else if (sp->defined == (N_UNDF|N_EXT))
167                         fprintf(outfile, "common: size %#x", sp->common_size);
168                 else
169                         fprintf(outfile, "type %d, value %#lx, size %#x",
170                                 sp->defined, sp->value, sp->size);
171                 if (sp->alias)
172                         fprintf(outfile, ", aliased to %s", demangle(sp->alias->name));
173                 fprintf(outfile, "\n");
174         } END_EACH_SYMBOL;
175
176         each_file(list_file_locals, (void *)outfile);
177 }
178
179 static void
180 describe_file_sections(entry, outfile)
181         struct file_entry *entry;
182         FILE           *outfile;
183 {
184         fprintf(outfile, "  ");
185         print_file_name(entry, outfile);
186         if (entry->flags & (E_JUST_SYMS | E_DYNAMIC))
187                 fprintf(outfile, " symbols only\n");
188         else
189                 fprintf(outfile,
190                         " text %x(%lx), data %x(%lx), bss %x(%lx) hex\n",
191                         entry->text_start_address,
192                         (unsigned long)entry->header.a_text,
193                         entry->data_start_address,
194                         (unsigned long)entry->header.a_data,
195                         entry->bss_start_address,
196                         (unsigned long)entry->header.a_bss);
197 }
198
199 static void
200 list_file_locals (entry, outfile)
201      struct file_entry *entry;
202      FILE *outfile;
203 {
204         struct localsymbol      *lsp, *lspend;
205
206         entry->strings = (char *)alloca(entry->string_size);
207         read_entry_strings (file_open(entry), entry);
208
209         fprintf (outfile, "\nLocal symbols of ");
210         print_file_name (entry, outfile);
211         fprintf (outfile, ":\n\n");
212
213         lspend = entry->symbols + entry->nsymbols;
214         for (lsp = entry->symbols; lsp < lspend; lsp++) {
215                 register struct nlist *p = &lsp->nzlist.nlist;
216                 /*
217                  * If this is a definition,
218                  * update it if necessary by this file's start address.
219                  */
220                 if (!(p->n_type & (N_STAB | N_EXT)))
221                         fprintf(outfile, "  %s: 0x%lx\n",
222                                 entry->strings + p->n_un.n_strx, p->n_value);
223         }
224
225         entry->strings = 0;             /* All done with them.  */
226 }
227
228
229 /* Static vars for do_warnings and subroutines of it */
230 static int list_unresolved_refs;        /* List unresolved refs */
231 static int list_multiple_defs;          /* List multiple definitions */
232
233 static struct line_debug_entry *init_debug_scan __P((int, struct file_entry *));
234 static int      next_debug_entry __P((int, struct line_debug_entry *));
235 static int      address_to_line __P((unsigned long, struct line_debug_entry *));
236
237 /*
238  * Structure for communication between do_file_warnings and it's
239  * helper routines.  Will in practice be an array of three of these:
240  * 0) Current line, 1) Next line, 2) Source file info.
241  */
242 struct line_debug_entry
243 {
244         int                     line;
245         char                    *filename;
246         struct localsymbol      *sym;
247 };
248
249 /*
250  * Helper routines for do_file_warnings.
251  */
252
253 /*
254  * Return an integer less than, equal to, or greater than 0 as per the
255  * relation between the two relocation entries.  Used by qsort.
256  */
257
258 static int
259 reloc_cmp(rel1, rel2)
260         struct relocation_info *rel1, *rel2;
261 {
262         return RELOC_ADDRESS(rel1) - RELOC_ADDRESS(rel2);
263 }
264
265 /*
266  * Moves to the next debugging symbol in the file.  USE_DATA_SYMBOLS
267  * determines the type of the debugging symbol to look for (DSLINE or
268  * SLINE).  STATE_POINTER keeps track of the old and new locatiosn in
269  * the file.  It assumes that state_pointer[1] is valid; ie
270  * that it.sym points into some entry in the symbol table.  If
271  * state_pointer[1].sym == 0, this routine should not be called.
272  */
273
274 static int
275 next_debug_entry(use_data_symbols, state_pointer)
276         register int use_data_symbols;
277         /* Next must be passed by reference! */
278         struct line_debug_entry state_pointer[3];
279 {
280         register struct line_debug_entry
281                                 *current = state_pointer,
282                                 *next = state_pointer + 1,
283                                 /* Used to store source file */
284                                 *source = state_pointer + 2;
285
286         struct file_entry       *entry = (struct file_entry *)source->sym;
287         struct localsymbol      *lspend = entry->symbols + entry->nsymbols;
288
289
290         current->sym = next->sym;
291         current->line = next->line;
292         current->filename = next->filename;
293
294         while (++(next->sym) < lspend) {
295
296                 struct nlist    *np = &next->sym->nzlist.nlist;
297
298                 /*
299                  * n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80,
300                  * so may look negative...therefore, must mask to low bits
301                  */
302                 switch (np->n_type & 0xff) {
303                 case N_SLINE:
304                         if (use_data_symbols)
305                                 continue;
306                         next->line = np->n_desc;
307                         return 1;
308                 case N_DSLINE:
309                         if (!use_data_symbols)
310                                 continue;
311                         next->line = np->n_desc;
312                         return 1;
313 #ifdef HAVE_SUN_STABS
314                 case N_EINCL:
315                         next->filename = source->filename;
316                         continue;
317 #endif
318                 case N_SO:
319                         source->filename = np->n_un.n_strx + entry->strings;
320                         source->line++;
321 #ifdef HAVE_SUN_STABS
322                 case N_BINCL:
323 #endif
324                 case N_SOL:
325                         next->filename = np->n_un.n_strx + entry->strings;
326                 default:
327                         continue;
328                 }
329         }
330         next->sym = (struct localsymbol *)0;
331         return 0;
332 }
333
334 /*
335  * Create a structure to save the state of a scan through the debug symbols.
336  * USE_DATA_SYMBOLS is set if we should be scanning for DSLINE's instead of
337  * SLINE's. ENTRY is the file entry which points at the symbols to use.
338  */
339
340 static struct line_debug_entry *
341 init_debug_scan(use_data_symbols, entry)
342         int                     use_data_symbols;
343         struct file_entry       *entry;
344 {
345         register struct localsymbol     *lsp, *lspend;
346         struct line_debug_entry *state_pointer, *current, *next, *source;
347
348         state_pointer = (struct line_debug_entry *)
349                 xmalloc(3 * sizeof(*state_pointer));
350
351         current = state_pointer,
352         next = state_pointer + 1,
353         source = state_pointer + 2;     /* Used to store source file */
354
355         lspend = entry->symbols+entry->nsymbols;
356
357         for (lsp = entry->symbols; lsp < lspend; lsp++)
358                 if (lsp->nzlist.nlist.n_type == N_SO)
359                         break;
360
361         if (lsp >= lspend) {
362                 /* I believe this translates to "We lose" */
363                 current->filename = next->filename = entry->filename;
364                 current->line = next->line = -1;
365                 current->sym = next->sym = (struct localsymbol *)0;
366                 return state_pointer;
367         }
368         next->line = source->line = 0;
369         next->filename = source->filename
370                         = (lsp->nzlist.nlist.n_un.n_strx + entry->strings);
371         source->sym = (struct localsymbol *)entry;
372         next->sym = lsp;
373
374         /* To setup next */
375         next_debug_entry(use_data_symbols, state_pointer);
376
377         if (!next->sym) {       /* No line numbers for this section; */
378                 /* setup output results as appropriate */
379                 if (source->line) {
380                         current->filename = source->filename = entry->filename;
381                         current->line = -1;     /* Don't print lineno */
382                 } else {
383                         current->filename = source->filename;
384                         current->line = 0;
385                 }
386                 return state_pointer;
387         }
388         /* To setup current */
389         next_debug_entry(use_data_symbols, state_pointer);
390
391         return state_pointer;
392 }
393
394 /*
395  * Takes an ADDRESS (in either text or data space) and a STATE_POINTER which
396  * describes the current location in the implied scan through the debug
397  * symbols within the file which ADDRESS is within, and returns the source
398  * line number which corresponds to ADDRESS.
399  */
400
401 static int
402 address_to_line(address, state_pointer)
403         unsigned long   address;
404 /* Next must be passed by reference! */
405         struct line_debug_entry state_pointer[3];
406 {
407         struct line_debug_entry *current, *next, *tmp_pointer;
408         int                     use_data_symbols;
409
410         current = state_pointer;
411         next = state_pointer + 1;
412
413         if (next->sym)
414                 use_data_symbols =
415                         (next->sym->nzlist.nlist.n_type & N_TYPE) == N_DATA;
416         else
417                 return current->line;
418
419         /* Go back to the beginning if we've already passed it. */
420         if (current->sym->nzlist.nlist.n_value > address) {
421                 tmp_pointer = init_debug_scan(use_data_symbols,
422                                               (struct file_entry *)
423                                               ((state_pointer + 2)->sym));
424                 state_pointer[0] = tmp_pointer[0];
425                 state_pointer[1] = tmp_pointer[1];
426                 state_pointer[2] = tmp_pointer[2];
427                 free(tmp_pointer);
428         }
429
430         /* If we're still in a bad way, return -1, meaning invalid line. */
431         if (current->sym->nzlist.nlist.n_value > address)
432                 return -1;
433
434         while (next->sym
435                && next->sym->nzlist.nlist.n_value <= address
436                && next_debug_entry(use_data_symbols, state_pointer));
437
438         return current->line;
439 }
440
441
442 /* Macros for manipulating bitvectors.  */
443 #define BIT_SET_P(bv, index)    ((bv)[(index) >> 3] & 1 << ((index) & 0x7))
444 #define SET_BIT(bv, index)      ((bv)[(index) >> 3] |= 1 << ((index) & 0x7))
445
446 /*
447  * This routine will scan through the relocation data of file ENTRY, printing
448  * out references to undefined symbols and references to symbols defined in
449  * files with N_WARNING symbols.  If DATA_SEGMENT is non-zero, it will scan
450  * the data relocation segment (and use N_DSLINE symbols to track line
451  * number); otherwise it will scan the text relocation segment.  Warnings
452  * will be printed on the output stream OUTFILE.  Eventually, every nlist
453  * symbol mapped through will be marked in the NLIST_BITVECTOR, so we don't
454  * repeat ourselves when we scan the nlists themselves.
455  */
456
457 static void
458 do_relocation_warnings(entry, data_segment, outfile, nlist_bitvector)
459         struct file_entry *entry;
460         int             data_segment;
461         FILE           *outfile;
462         unsigned char  *nlist_bitvector;
463 {
464         struct relocation_info  *rp, *erp;
465         int                     start_of_segment;
466         struct localsymbol      *start_of_syms;
467         struct line_debug_entry *state_pointer, *current;
468         /* Assigned to generally static values; should not be written into.  */
469         char *errfmt;
470         /*
471          * Assigned to alloca'd values cand copied into; should be freed when
472          * done.
473          */
474         char *errmsg;
475         int  invalidate_line_number;
476
477         rp = data_segment ? entry->datarel : entry->textrel;
478         erp = data_segment ? (rp + entry->ndatarel) : (rp + entry->ntextrel);
479         start_of_syms = entry->symbols;
480         start_of_segment = (data_segment ?
481                 entry->data_start_address :
482                 entry->text_start_address);
483         state_pointer = init_debug_scan(data_segment != 0, entry);
484         current = state_pointer;
485
486         /*
487          * We need to sort the relocation info here.  Sheesh, so much effort
488          * for one lousy error optimization.
489          */
490         qsort(rp, erp - rp, sizeof(rp[0]), reloc_cmp);
491
492         for (; rp < erp; rp++) {
493                 register struct localsymbol *lsp;
494                 register symbol *g;
495
496                 /*
497                  * If the relocation isn't resolved through a symbol, continue.
498                  */
499                 if (!RELOC_EXTERN_P(rp))
500                         continue;
501
502                 lsp = &entry->symbols[RELOC_SYMBOL(rp)];
503
504                 /*
505                  * Local symbols shouldn't ever be used by relocation info,
506                  * so the next should be safe. This is, of course, wrong.
507                  * References to local BSS symbols can be the targets of
508                  * relocation info, and they can (must) be resolved through
509                  * symbols.  However, these must be defined properly, (the
510                  * assembler would have caught it otherwise), so we can
511                  * ignore these cases.
512                  */
513
514                 if ((g = lsp->symbol) == NULL)
515                         continue;
516
517                 if (!(lsp->nzlist.nz_type & N_EXT) &&
518                     !SET_ELEMENT_P(lsp->nzlist.nz_type)) {
519                         warnx("internal error: `%s' N_EXT not set", demangle(g->name));
520                         continue;
521                 }
522
523                 errmsg = 0;
524
525                 if (!g->defined && !g->so_defined && list_unresolved_refs) {
526                         /* Mark as being noted by relocation warning pass. */
527                         SET_BIT(nlist_bitvector, lsp - start_of_syms);
528
529                         if (g->undef_refs == 0)
530                                 reported_undefineds++;
531                         if (g->undef_refs >= MAX_UREFS_PRINTED)
532                                 /* Listed too many */
533                                 continue;
534                         /* Undefined symbol which we should mention */
535
536                         if (++(g->undef_refs) == MAX_UREFS_PRINTED) {
537                                 errfmt = "More undefined symbol %s refs follow";
538                                 invalidate_line_number = 1;
539                         } else {
540                                 errfmt =
541                         "Undefined symbol `%s' referenced from %s segment";
542                                 invalidate_line_number = 0;
543                         }
544                 } else {        /* Defined */
545                         /* Potential symbol warning here */
546                         if (!g->warning)
547                                 continue;
548
549                         if (BIT_SET_P(nlist_bitvector, lsp - start_of_syms))
550                                 continue;
551
552                         /* Mark as being noted by relocation warning pass.  */
553                         SET_BIT(nlist_bitvector, lsp - start_of_syms);
554
555                         errfmt = 0;
556                         errmsg = g->warning;
557                         invalidate_line_number = 0;
558                 }
559
560
561                 /* If errfmt == 0, errmsg has already been defined.  */
562                 if (errfmt != 0) {
563                         char *nm = demangle(g->name);
564                         errmsg = (char *)
565                                 xmalloc(strlen(errfmt) + strlen(nm) + 1);
566                         sprintf(errmsg, errfmt, nm, data_segment?"data":"text");
567                 }
568                 address_to_line(RELOC_ADDRESS(rp) + start_of_segment,
569                                 state_pointer);
570
571                 if (current->line >= 0)
572                         fprintf(outfile, "%s:%d: %s\n",
573                                 current->filename,
574                                 invalidate_line_number ? 0 : current->line,
575                                 errmsg);
576                 else
577                         fprintf(outfile, "%s: %s\n", current->filename, errmsg);
578
579                 if (errfmt != 0)
580                         free(errmsg);
581         }
582
583         free(state_pointer);
584 }
585
586 /*
587  * Print on OUTFILE a list of all warnings generated by references and/or
588  * definitions in the file ENTRY.  List source file and line number if
589  * possible, just the .o file if not.
590  */
591
592 void
593 do_file_warnings (entry, outfile)
594         struct file_entry       *entry;
595         FILE                    *outfile;
596 {
597         int     nsym;
598         int     i;
599         char    *errfmt, *file_name;
600         int     line_number;
601         int     dont_allow_symbol_name;
602         u_char  *nlist_bitvector;
603         struct line_debug_entry *text_scan, *data_scan;
604
605         nsym = entry->nsymbols;
606         nlist_bitvector = (u_char *)alloca((nsym >> 3) + 1);
607         bzero(nlist_bitvector, (nsym >> 3) + 1);
608
609         /* Read in the strings */
610         entry->strings = (char *)alloca(entry->string_size);
611         read_entry_strings(file_open(entry), entry);
612
613         if (!(entry->flags & E_DYNAMIC)) {
614                 /* Do text warnings based on a scan through the reloc info. */
615                 do_relocation_warnings(entry, 0, outfile, nlist_bitvector);
616
617                 /* Do data warnings based on a scan through the reloc info. */
618                 do_relocation_warnings(entry, 1, outfile, nlist_bitvector);
619         }
620
621         /*
622          * Scan through all of the nlist entries in this file and pick up
623          * anything that the scan through the relocation stuff didn't.
624          */
625         text_scan = init_debug_scan(0, entry);
626         data_scan = init_debug_scan(1, entry);
627
628         for (i = 0; i < nsym; i++) {
629                 struct nlist *np;
630                 symbol *g;
631
632                 g = entry->symbols[i].symbol;
633                 np = &entry->symbols[i].nzlist.nlist;
634
635                 if (g == NULL)
636                         continue;
637
638                 if (!(np->n_type & N_EXT) && !SET_ELEMENT_P(np->n_type)) {
639                         warnx("internal error: `%s' N_EXT not set", demangle(g->name));
640                         continue;
641                 }
642
643                 if (!(g->flags & GS_REFERENCED)) {
644 #if 0
645                         /* Check for undefined shobj symbols */
646                         struct localsymbol      *lsp;
647                         register int            type;
648
649                         for (lsp = g->sorefs; lsp; lsp = lsp->next) {
650                                 type = lsp->nzlist.nz_type;
651                                 if ((type & N_EXT) &&
652                                                 type != (N_UNDF | N_EXT)) {
653                                         break;
654                                 }
655                         }
656                         if (type == (N_UNDF | N_EXT)) {
657                                 fprintf(stderr,
658                                         "Undefined symbol %s referenced from %s\n",
659                                         demangle(g->name),
660                                         get_file_name(entry));
661                         }
662 #endif
663                         continue;
664                 }
665
666                 dont_allow_symbol_name = 0;
667
668                 if (list_multiple_defs && g->mult_defs) {
669
670                         errfmt = "Definition of symbol `%s' (multiply defined)";
671                         switch (np->n_type) {
672                         case N_TEXT | N_EXT:
673                                 line_number =
674                                         address_to_line(np->n_value, text_scan);
675                                 file_name = text_scan[0].filename;
676                                 break;
677
678                         case N_DATA | N_EXT:
679                                 line_number =
680                                         address_to_line(np->n_value, data_scan);
681                                 file_name = data_scan[0].filename;
682                                 break;
683
684                         case N_SETA | N_EXT:
685                         case N_SETT | N_EXT:
686                         case N_SETD | N_EXT:
687                         case N_SETB | N_EXT:
688                                 if (g->mult_defs == 2)
689                                         continue;
690                                 errfmt =
691         "First set element definition of symbol `%s' (multiply defined)";
692                                 line_number = -1;
693                                 break;
694
695                         case N_SIZE | N_EXT:
696                                 errfmt =
697         "Size element definition of symbol `%s' (multiply defined)";
698                                 line_number = -1;
699                                 break;
700
701                         case N_INDR | N_EXT:
702                                 errfmt =
703         "Alias definition of symbol `%s' (multiply defined)";
704                                 line_number = -1;
705                                 break;
706
707                         case N_UNDF | N_EXT:
708                                 /* Don't print out multiple defs at references.*/
709                                 continue;
710
711                         default:
712                                 warnx("%s: unexpected multiple definitions "
713                                       "of symbol `%s', type %#x",
714                                       get_file_name(entry),
715                                       demangle(g->name), np->n_type);
716                                 break;
717                         }
718
719                 } else if (BIT_SET_P(nlist_bitvector, i)) {
720                         continue;
721                 } else if (list_unresolved_refs &&
722                            !g->defined && !g->so_defined) {
723
724                         if (g->undef_refs == 0)
725                                 reported_undefineds++;
726                         if (g->undef_refs >= MAX_UREFS_PRINTED)
727                                 continue;
728                         if (++(g->undef_refs) == MAX_UREFS_PRINTED)
729                                 errfmt = "More undefined `%s' refs follow";
730                         else
731                                 errfmt = "Undefined symbol `%s' referenced";
732                         line_number = -1;
733                 } else if (g->def_lsp && g->def_lsp->entry != entry &&
734                            !(entry->flags & E_DYNAMIC) &&
735                            g->def_lsp->entry->flags & E_SECONDCLASS) {
736                         fprintf(outfile,
737                         "%s: Undefined symbol `%s' referenced (use %s ?)\n",
738                                 get_file_name(entry),
739                                 demangle(g->name),
740                                 g->def_lsp->entry->local_sym_name);
741                         continue;
742                 } else if (g->warning) {
743                         /*
744                          * There are two cases in which we don't want to do
745                          * this. The first is if this is a definition instead
746                          * of a reference. The second is if it's the reference
747                          * used by the warning stabs itself.
748                          */
749                         if (np->n_type != (N_EXT | N_UNDF) ||
750                             (entry->symbols[i].flags & LS_WARNING))
751                                 continue;
752
753                         errfmt = g->warning;
754                         line_number = -1;
755                         dont_allow_symbol_name = 1;
756                 } else
757                         continue;
758
759                 if (line_number == -1)
760                         fprintf(outfile, "%s: ", get_file_name(entry));
761                 else
762                         fprintf(outfile, "%s:%d: ", file_name, line_number);
763
764                 if (dont_allow_symbol_name)
765                         fprintf(outfile, "%s", errfmt);
766                 else
767                         fprintf(outfile, errfmt, demangle(g->name));
768
769                 fputc('\n', outfile);
770         }
771         free(text_scan);
772         free(data_scan);
773         entry->strings = 0;     /* Since it will disappear anyway. */
774 }
775
776 int
777 do_warnings(outfile)
778         FILE    *outfile;
779 {
780
781         list_unresolved_refs = !relocatable_output &&
782                 ( (undefined_global_sym_count - undefined_weak_sym_count) > 0
783                    || undefined_shobj_sym_count
784                 );
785         list_multiple_defs = multiple_def_count != 0;
786
787         if (!(list_unresolved_refs ||
788               list_warning_symbols ||
789               list_multiple_defs))
790                 /* No need to run this routine */
791                 return 1;
792
793         if (entry_symbol && !entry_symbol->defined)
794                 fprintf(outfile, "Undefined entry symbol `%s'\n",
795                         demangle(entry_symbol->name));
796
797         each_file(do_file_warnings, (void *)outfile);
798
799         if (list_unresolved_refs &&
800             reported_undefineds !=
801             (undefined_global_sym_count - undefined_weak_sym_count))
802                 warnx("Spurious undefined symbols: "
803                       "# undefined symbols %d, reported %d",
804                       (undefined_global_sym_count - undefined_weak_sym_count),
805                       reported_undefineds);
806
807         if (list_unresolved_refs || list_multiple_defs)
808                 return 0;
809
810         return 1;
811 }