summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/ld/warnings.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/ld/warnings.c')
-rw-r--r--gnu/usr.bin/ld/warnings.c810
1 files changed, 0 insertions, 810 deletions
diff --git a/gnu/usr.bin/ld/warnings.c b/gnu/usr.bin/ld/warnings.c
deleted file mode 100644
index 2c988d5..0000000
--- a/gnu/usr.bin/ld/warnings.c
+++ /dev/null
@@ -1,810 +0,0 @@
-/*-
- * This code is derived from software copyrighted by the Free Software
- * Foundation.
- *
- * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
- *
- * Modified 1993 by Paul Kranenburg, Erasmus University
- */
-
-/* Derived from ld.c: "@(#)ld.c 6.10 (Berkeley) 5/22/91"; */
-
-/* Linker `ld' for GNU
- Copyright (C) 1988 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* Written by Richard Stallman with some help from Eric Albert.
- Set, indirect, and warning symbol features added by Randy Smith. */
-
-/*
- * $FreeBSD$
- */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/file.h>
-#include <sys/time.h>
-#include <sys/errno.h>
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <ar.h>
-#include <ranlib.h>
-#include <a.out.h>
-#include <stab.h>
-#include <string.h>
-#if __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#endif
-
-#include "ld.h"
-#include "dynamic.h"
-
-static int reported_undefineds;
-
-#ifdef DEMANGLE_CPLUSPLUS
-#include "demangle.h"
-
-char *demangle(name)
- char *name;
-{
- static char* saved_result = NULL;
-
- if (saved_result)
- free (saved_result);
-
- saved_result = cplus_demangle (name[0] == '_' ? name + 1 : name, DMGL_PARAMS | DMGL_ANSI);
-
- if (saved_result)
- return saved_result;
- else
- return name;
-}
-#endif
-
-/*
- * Print the filename of ENTRY on OUTFILE (a stdio stream),
- * and then a newline.
- */
-
-void
-prline_file_name (entry, outfile)
- struct file_entry *entry;
- FILE *outfile;
-{
- print_file_name (entry, outfile);
- fprintf (outfile, "\n");
-}
-
-/*
- * Print the filename of ENTRY on OUTFILE (a stdio stream).
- */
-
-void
-print_file_name (entry, outfile)
- struct file_entry *entry;
- FILE *outfile;
-{
- if (entry == NULL) {
- fprintf (outfile, "NULL");
- }
-
- if (entry->superfile) {
- print_file_name (entry->superfile, outfile);
- fprintf (outfile, "(%s)", entry->filename);
- } else
- fprintf (outfile, "%s", entry->filename);
-}
-
-/*
- * Return the filename of entry as a string (malloc'd for the purpose)
- */
-
-char *
-get_file_name (entry)
- struct file_entry *entry;
-{
- char *result, *supfile;
-
- if (entry == NULL) {
- return (char *)strdup("NULL");
- }
-
- if (entry->superfile) {
- supfile = get_file_name(entry->superfile);
- result = (char *)
- xmalloc(strlen(supfile) + strlen(entry->filename) + 3);
- (void)sprintf(result, "%s(%s)", supfile, entry->filename);
- free(supfile);
-
- } else {
- result = (char *)xmalloc(strlen(entry->filename) + 1);
- strcpy(result, entry->filename);
- }
- return result;
-}
-
-/* Print a complete or partial map of the output file. */
-
-static void describe_file_sections __P((struct file_entry *, FILE *));
-static void list_file_locals __P((struct file_entry *, FILE *));
-
-void
-print_symbols(outfile)
- FILE *outfile;
-{
- fprintf(outfile, "\nFiles:\n\n");
- each_file(describe_file_sections, (void *)outfile);
-
- fprintf(outfile, "\nGlobal symbols:\n\n");
- FOR_EACH_SYMBOL(i, sp) {
- fprintf(outfile, " %s: ", demangle(sp->name));
- if (!(sp->flags & GS_REFERENCED))
- fprintf(outfile, "unreferenced");
- else if (sp->so_defined)
- fprintf(outfile, "sodefined");
- else if (!sp->defined)
- fprintf(outfile, "undefined");
- else if (sp->defined == (N_UNDF|N_EXT))
- fprintf(outfile, "common: size %#x", sp->common_size);
- else
- fprintf(outfile, "type %d, value %#lx, size %#x",
- sp->defined, sp->value, sp->size);
- if (sp->alias)
- fprintf(outfile, ", aliased to %s", demangle(sp->alias->name));
- fprintf(outfile, "\n");
- } END_EACH_SYMBOL;
-
- each_file(list_file_locals, (void *)outfile);
-}
-
-static void
-describe_file_sections(entry, outfile)
- struct file_entry *entry;
- FILE *outfile;
-{
- fprintf(outfile, " ");
- print_file_name(entry, outfile);
- if (entry->flags & (E_JUST_SYMS | E_DYNAMIC))
- fprintf(outfile, " symbols only\n");
- else
- fprintf(outfile,
- " text %x(%lx), data %x(%lx), bss %x(%lx) hex\n",
- entry->text_start_address,
- (unsigned long)entry->header.a_text,
- entry->data_start_address,
- (unsigned long)entry->header.a_data,
- entry->bss_start_address,
- (unsigned long)entry->header.a_bss);
-}
-
-static void
-list_file_locals (entry, outfile)
- struct file_entry *entry;
- FILE *outfile;
-{
- struct localsymbol *lsp, *lspend;
-
- entry->strings = (char *)alloca(entry->string_size);
- read_entry_strings (file_open(entry), entry);
-
- fprintf (outfile, "\nLocal symbols of ");
- print_file_name (entry, outfile);
- fprintf (outfile, ":\n\n");
-
- lspend = entry->symbols + entry->nsymbols;
- for (lsp = entry->symbols; lsp < lspend; lsp++) {
- register struct nlist *p = &lsp->nzlist.nlist;
- /*
- * If this is a definition,
- * update it if necessary by this file's start address.
- */
- if (!(p->n_type & (N_STAB | N_EXT)))
- fprintf(outfile, " %s: 0x%lx\n",
- entry->strings + p->n_un.n_strx, p->n_value);
- }
-
- entry->strings = 0; /* All done with them. */
-}
-
-
-/* Static vars for do_warnings and subroutines of it */
-static int list_unresolved_refs; /* List unresolved refs */
-static int list_multiple_defs; /* List multiple definitions */
-
-static struct line_debug_entry *init_debug_scan __P((int, struct file_entry *));
-static int next_debug_entry __P((int, struct line_debug_entry *));
-static int address_to_line __P((unsigned long, struct line_debug_entry *));
-
-/*
- * Structure for communication between do_file_warnings and it's
- * helper routines. Will in practice be an array of three of these:
- * 0) Current line, 1) Next line, 2) Source file info.
- */
-struct line_debug_entry
-{
- int line;
- char *filename;
- struct localsymbol *sym;
-};
-
-/*
- * Helper routines for do_file_warnings.
- */
-
-/*
- * Return an integer less than, equal to, or greater than 0 as per the
- * relation between the two relocation entries. Used by qsort.
- */
-
-static int
-reloc_cmp(rel1, rel2)
- struct relocation_info *rel1, *rel2;
-{
- return RELOC_ADDRESS(rel1) - RELOC_ADDRESS(rel2);
-}
-
-/*
- * Moves to the next debugging symbol in the file. USE_DATA_SYMBOLS
- * determines the type of the debugging symbol to look for (DSLINE or
- * SLINE). STATE_POINTER keeps track of the old and new locatiosn in
- * the file. It assumes that state_pointer[1] is valid; ie
- * that it.sym points into some entry in the symbol table. If
- * state_pointer[1].sym == 0, this routine should not be called.
- */
-
-static int
-next_debug_entry(use_data_symbols, state_pointer)
- register int use_data_symbols;
- /* Next must be passed by reference! */
- struct line_debug_entry state_pointer[3];
-{
- register struct line_debug_entry
- *current = state_pointer,
- *next = state_pointer + 1,
- /* Used to store source file */
- *source = state_pointer + 2;
-
- struct file_entry *entry = (struct file_entry *)source->sym;
- struct localsymbol *lspend = entry->symbols + entry->nsymbols;
-
-
- current->sym = next->sym;
- current->line = next->line;
- current->filename = next->filename;
-
- while (++(next->sym) < lspend) {
-
- struct nlist *np = &next->sym->nzlist.nlist;
-
- /*
- * n_type is a char, and N_SOL, N_EINCL and N_BINCL are > 0x80,
- * so may look negative...therefore, must mask to low bits
- */
- switch (np->n_type & 0xff) {
- case N_SLINE:
- if (use_data_symbols)
- continue;
- next->line = np->n_desc;
- return 1;
- case N_DSLINE:
- if (!use_data_symbols)
- continue;
- next->line = np->n_desc;
- return 1;
-#ifdef HAVE_SUN_STABS
- case N_EINCL:
- next->filename = source->filename;
- continue;
-#endif
- case N_SO:
- source->filename = np->n_un.n_strx + entry->strings;
- source->line++;
-#ifdef HAVE_SUN_STABS
- case N_BINCL:
-#endif
- case N_SOL:
- next->filename = np->n_un.n_strx + entry->strings;
- default:
- continue;
- }
- }
- next->sym = (struct localsymbol *)0;
- return 0;
-}
-
-/*
- * Create a structure to save the state of a scan through the debug symbols.
- * USE_DATA_SYMBOLS is set if we should be scanning for DSLINE's instead of
- * SLINE's. ENTRY is the file entry which points at the symbols to use.
- */
-
-static struct line_debug_entry *
-init_debug_scan(use_data_symbols, entry)
- int use_data_symbols;
- struct file_entry *entry;
-{
- register struct localsymbol *lsp, *lspend;
- struct line_debug_entry *state_pointer, *current, *next, *source;
-
- state_pointer = (struct line_debug_entry *)
- xmalloc(3 * sizeof(*state_pointer));
-
- current = state_pointer,
- next = state_pointer + 1,
- source = state_pointer + 2; /* Used to store source file */
-
- lspend = entry->symbols+entry->nsymbols;
-
- for (lsp = entry->symbols; lsp < lspend; lsp++)
- if (lsp->nzlist.nlist.n_type == N_SO)
- break;
-
- if (lsp >= lspend) {
- /* I believe this translates to "We lose" */
- current->filename = next->filename = entry->filename;
- current->line = next->line = -1;
- current->sym = next->sym = (struct localsymbol *)0;
- return state_pointer;
- }
- next->line = source->line = 0;
- next->filename = source->filename
- = (lsp->nzlist.nlist.n_un.n_strx + entry->strings);
- source->sym = (struct localsymbol *)entry;
- next->sym = lsp;
-
- /* To setup next */
- next_debug_entry(use_data_symbols, state_pointer);
-
- if (!next->sym) { /* No line numbers for this section; */
- /* setup output results as appropriate */
- if (source->line) {
- current->filename = source->filename = entry->filename;
- current->line = -1; /* Don't print lineno */
- } else {
- current->filename = source->filename;
- current->line = 0;
- }
- return state_pointer;
- }
- /* To setup current */
- next_debug_entry(use_data_symbols, state_pointer);
-
- return state_pointer;
-}
-
-/*
- * Takes an ADDRESS (in either text or data space) and a STATE_POINTER which
- * describes the current location in the implied scan through the debug
- * symbols within the file which ADDRESS is within, and returns the source
- * line number which corresponds to ADDRESS.
- */
-
-static int
-address_to_line(address, state_pointer)
- unsigned long address;
-/* Next must be passed by reference! */
- struct line_debug_entry state_pointer[3];
-{
- struct line_debug_entry *current, *next, *tmp_pointer;
- int use_data_symbols;
-
- current = state_pointer;
- next = state_pointer + 1;
-
- if (next->sym)
- use_data_symbols =
- (next->sym->nzlist.nlist.n_type & N_TYPE) == N_DATA;
- else
- return current->line;
-
- /* Go back to the beginning if we've already passed it. */
- if (current->sym->nzlist.nlist.n_value > address) {
- tmp_pointer = init_debug_scan(use_data_symbols,
- (struct file_entry *)
- ((state_pointer + 2)->sym));
- state_pointer[0] = tmp_pointer[0];
- state_pointer[1] = tmp_pointer[1];
- state_pointer[2] = tmp_pointer[2];
- free(tmp_pointer);
- }
-
- /* If we're still in a bad way, return -1, meaning invalid line. */
- if (current->sym->nzlist.nlist.n_value > address)
- return -1;
-
- while (next->sym
- && next->sym->nzlist.nlist.n_value <= address
- && next_debug_entry(use_data_symbols, state_pointer));
-
- return current->line;
-}
-
-
-/* Macros for manipulating bitvectors. */
-#define BIT_SET_P(bv, index) ((bv)[(index) >> 3] & 1 << ((index) & 0x7))
-#define SET_BIT(bv, index) ((bv)[(index) >> 3] |= 1 << ((index) & 0x7))
-
-/*
- * This routine will scan through the relocation data of file ENTRY, printing
- * out references to undefined symbols and references to symbols defined in
- * files with N_WARNING symbols. If DATA_SEGMENT is non-zero, it will scan
- * the data relocation segment (and use N_DSLINE symbols to track line
- * number); otherwise it will scan the text relocation segment. Warnings
- * will be printed on the output stream OUTFILE. Eventually, every nlist
- * symbol mapped through will be marked in the NLIST_BITVECTOR, so we don't
- * repeat ourselves when we scan the nlists themselves.
- */
-
-static void
-do_relocation_warnings(entry, data_segment, outfile, nlist_bitvector)
- struct file_entry *entry;
- int data_segment;
- FILE *outfile;
- unsigned char *nlist_bitvector;
-{
- struct relocation_info *rp, *erp;
- int start_of_segment;
- struct localsymbol *start_of_syms;
- struct line_debug_entry *state_pointer, *current;
- /* Assigned to generally static values; should not be written into. */
- char *errfmt;
- /*
- * Assigned to alloca'd values cand copied into; should be freed when
- * done.
- */
- char *errmsg;
- int invalidate_line_number;
-
- rp = data_segment ? entry->datarel : entry->textrel;
- erp = data_segment ? (rp + entry->ndatarel) : (rp + entry->ntextrel);
- start_of_syms = entry->symbols;
- start_of_segment = (data_segment ?
- entry->data_start_address :
- entry->text_start_address);
- state_pointer = init_debug_scan(data_segment != 0, entry);
- current = state_pointer;
-
- /*
- * We need to sort the relocation info here. Sheesh, so much effort
- * for one lousy error optimization.
- */
- qsort(rp, erp - rp, sizeof(rp[0]), reloc_cmp);
-
- for (; rp < erp; rp++) {
- register struct localsymbol *lsp;
- register symbol *g;
-
- /*
- * If the relocation isn't resolved through a symbol, continue.
- */
- if (!RELOC_EXTERN_P(rp))
- continue;
-
- lsp = &entry->symbols[RELOC_SYMBOL(rp)];
-
- /*
- * Local symbols shouldn't ever be used by relocation info,
- * so the next should be safe. This is, of course, wrong.
- * References to local BSS symbols can be the targets of
- * relocation info, and they can (must) be resolved through
- * symbols. However, these must be defined properly, (the
- * assembler would have caught it otherwise), so we can
- * ignore these cases.
- */
-
- if ((g = lsp->symbol) == NULL)
- continue;
-
- if (!(lsp->nzlist.nz_type & N_EXT) &&
- !SET_ELEMENT_P(lsp->nzlist.nz_type)) {
- warnx("internal error: `%s' N_EXT not set", demangle(g->name));
- continue;
- }
-
- errmsg = 0;
-
- if (!g->defined && !g->so_defined && list_unresolved_refs) {
- /* Mark as being noted by relocation warning pass. */
- SET_BIT(nlist_bitvector, lsp - start_of_syms);
-
- if (g->undef_refs == 0)
- reported_undefineds++;
- if (g->undef_refs >= MAX_UREFS_PRINTED)
- /* Listed too many */
- continue;
- /* Undefined symbol which we should mention */
-
- if (++(g->undef_refs) == MAX_UREFS_PRINTED) {
- errfmt = "More undefined symbol %s refs follow";
- invalidate_line_number = 1;
- } else {
- errfmt =
- "Undefined symbol `%s' referenced from %s segment";
- invalidate_line_number = 0;
- }
- } else { /* Defined */
- /* Potential symbol warning here */
- if (!g->warning)
- continue;
-
- if (BIT_SET_P(nlist_bitvector, lsp - start_of_syms))
- continue;
-
- /* Mark as being noted by relocation warning pass. */
- SET_BIT(nlist_bitvector, lsp - start_of_syms);
-
- errfmt = 0;
- errmsg = g->warning;
- invalidate_line_number = 0;
- }
-
-
- /* If errfmt == 0, errmsg has already been defined. */
- if (errfmt != 0) {
- char *nm = demangle(g->name);
- errmsg = (char *)
- xmalloc(strlen(errfmt) + strlen(nm) + 1);
- sprintf(errmsg, errfmt, nm, data_segment?"data":"text");
- }
- address_to_line(RELOC_ADDRESS(rp) + start_of_segment,
- state_pointer);
-
- if (current->line >= 0)
- fprintf(outfile, "%s:%d: %s\n",
- current->filename,
- invalidate_line_number ? 0 : current->line,
- errmsg);
- else
- fprintf(outfile, "%s: %s\n", current->filename, errmsg);
-
- if (errfmt != 0)
- free(errmsg);
- }
-
- free(state_pointer);
-}
-
-/*
- * Print on OUTFILE a list of all warnings generated by references and/or
- * definitions in the file ENTRY. List source file and line number if
- * possible, just the .o file if not.
- */
-
-void
-do_file_warnings (entry, outfile)
- struct file_entry *entry;
- FILE *outfile;
-{
- int nsym;
- int i;
- char *errfmt, *file_name;
- int line_number;
- int dont_allow_symbol_name;
- u_char *nlist_bitvector;
- struct line_debug_entry *text_scan, *data_scan;
-
- nsym = entry->nsymbols;
- nlist_bitvector = (u_char *)alloca((nsym >> 3) + 1);
- bzero(nlist_bitvector, (nsym >> 3) + 1);
-
- /* Read in the strings */
- entry->strings = (char *)alloca(entry->string_size);
- read_entry_strings(file_open(entry), entry);
-
- if (!(entry->flags & E_DYNAMIC)) {
- /* Do text warnings based on a scan through the reloc info. */
- do_relocation_warnings(entry, 0, outfile, nlist_bitvector);
-
- /* Do data warnings based on a scan through the reloc info. */
- do_relocation_warnings(entry, 1, outfile, nlist_bitvector);
- }
-
- /*
- * Scan through all of the nlist entries in this file and pick up
- * anything that the scan through the relocation stuff didn't.
- */
- text_scan = init_debug_scan(0, entry);
- data_scan = init_debug_scan(1, entry);
-
- for (i = 0; i < nsym; i++) {
- struct nlist *np;
- symbol *g;
-
- g = entry->symbols[i].symbol;
- np = &entry->symbols[i].nzlist.nlist;
-
- if (g == NULL)
- continue;
-
- if (!(np->n_type & N_EXT) && !SET_ELEMENT_P(np->n_type)) {
- warnx("internal error: `%s' N_EXT not set", demangle(g->name));
- continue;
- }
-
- if (!(g->flags & GS_REFERENCED)) {
-#if 0
- /* Check for undefined shobj symbols */
- struct localsymbol *lsp;
- register int type;
-
- for (lsp = g->sorefs; lsp; lsp = lsp->next) {
- type = lsp->nzlist.nz_type;
- if ((type & N_EXT) &&
- type != (N_UNDF | N_EXT)) {
- break;
- }
- }
- if (type == (N_UNDF | N_EXT)) {
- fprintf(stderr,
- "Undefined symbol %s referenced from %s\n",
- demangle(g->name),
- get_file_name(entry));
- }
-#endif
- continue;
- }
-
- dont_allow_symbol_name = 0;
-
- if (list_multiple_defs && g->mult_defs) {
-
- errfmt = "Definition of symbol `%s' (multiply defined)";
- switch (np->n_type) {
- case N_TEXT | N_EXT:
- line_number =
- address_to_line(np->n_value, text_scan);
- file_name = text_scan[0].filename;
- break;
-
- case N_DATA | N_EXT:
- line_number =
- address_to_line(np->n_value, data_scan);
- file_name = data_scan[0].filename;
- break;
-
- case N_SETA | N_EXT:
- case N_SETT | N_EXT:
- case N_SETD | N_EXT:
- case N_SETB | N_EXT:
- if (g->mult_defs == 2)
- continue;
- errfmt =
- "First set element definition of symbol `%s' (multiply defined)";
- line_number = -1;
- break;
-
- case N_SIZE | N_EXT:
- errfmt =
- "Size element definition of symbol `%s' (multiply defined)";
- line_number = -1;
- break;
-
- case N_INDR | N_EXT:
- errfmt =
- "Alias definition of symbol `%s' (multiply defined)";
- line_number = -1;
- break;
-
- case N_UNDF | N_EXT:
- /* Don't print out multiple defs at references.*/
- continue;
-
- default:
- warnx("%s: unexpected multiple definitions "
- "of symbol `%s', type %#x",
- get_file_name(entry),
- demangle(g->name), np->n_type);
- break;
- }
-
- } else if (BIT_SET_P(nlist_bitvector, i)) {
- continue;
- } else if (list_unresolved_refs &&
- !g->defined && !g->so_defined) {
-
- if (g->undef_refs == 0)
- reported_undefineds++;
- if (g->undef_refs >= MAX_UREFS_PRINTED)
- continue;
- if (++(g->undef_refs) == MAX_UREFS_PRINTED)
- errfmt = "More undefined `%s' refs follow";
- else
- errfmt = "Undefined symbol `%s' referenced";
- line_number = -1;
- } else if (g->def_lsp && g->def_lsp->entry != entry &&
- !(entry->flags & E_DYNAMIC) &&
- g->def_lsp->entry->flags & E_SECONDCLASS) {
- fprintf(outfile,
- "%s: Undefined symbol `%s' referenced (use %s ?)\n",
- get_file_name(entry),
- demangle(g->name),
- g->def_lsp->entry->local_sym_name);
- continue;
- } else if (g->warning) {
- /*
- * There are two cases in which we don't want to do
- * this. The first is if this is a definition instead
- * of a reference. The second is if it's the reference
- * used by the warning stabs itself.
- */
- if (np->n_type != (N_EXT | N_UNDF) ||
- (entry->symbols[i].flags & LS_WARNING))
- continue;
-
- errfmt = g->warning;
- line_number = -1;
- dont_allow_symbol_name = 1;
- } else
- continue;
-
- if (line_number == -1)
- fprintf(outfile, "%s: ", get_file_name(entry));
- else
- fprintf(outfile, "%s:%d: ", file_name, line_number);
-
- if (dont_allow_symbol_name)
- fprintf(outfile, "%s", errfmt);
- else
- fprintf(outfile, errfmt, demangle(g->name));
-
- fputc('\n', outfile);
- }
- free(text_scan);
- free(data_scan);
- entry->strings = 0; /* Since it will disappear anyway. */
-}
-
-int
-do_warnings(outfile)
- FILE *outfile;
-{
-
- list_unresolved_refs = !relocatable_output &&
- ( (undefined_global_sym_count - undefined_weak_sym_count) > 0
- || undefined_shobj_sym_count
- );
- list_multiple_defs = multiple_def_count != 0;
-
- if (!(list_unresolved_refs ||
- list_warning_symbols ||
- list_multiple_defs))
- /* No need to run this routine */
- return 1;
-
- if (entry_symbol && !entry_symbol->defined)
- fprintf(outfile, "Undefined entry symbol `%s'\n",
- demangle(entry_symbol->name));
-
- each_file(do_file_warnings, (void *)outfile);
-
- if (list_unresolved_refs &&
- reported_undefineds !=
- (undefined_global_sym_count - undefined_weak_sym_count))
- warnx("Spurious undefined symbols: "
- "# undefined symbols %d, reported %d",
- (undefined_global_sym_count - undefined_weak_sym_count),
- reported_undefineds);
-
- if (list_unresolved_refs || list_multiple_defs)
- return 0;
-
- return 1;
-}
OpenPOWER on IntegriCloud