add -warn-common option

This commit is contained in:
David MacKenzie 1993-08-03 22:47:28 +00:00
parent b6e7553c42
commit 2a28d8b006
6 changed files with 248 additions and 78 deletions

View file

@ -1,3 +1,15 @@
Tue Aug 3 10:57:41 1993 David J. Mackenzie (djm@thepub.cygnus.com)
* ldgram.y, ldlex.l, mri.c, ldwrite.c: Change multiple commons
into externs.
* ldmisc.c (multiple_warn): New function.
* ldmisc.h: Declare it.
* ldmain.c (enter_global_ref): Call it.
* ld.h (ld_config_type): Add warn_common.
* ldlex.l, ldgram.y: Set it with -warn-common option.
* ldver.c (help): Document it.
Mon Aug 2 12:04:36 1993 Ken Raeburn (raeburn@cambridge.cygnus.com)
* scripttempl/elf.sc: Add hooks for .sdata, .sbss, and

50
ld/ld.1
View file

@ -80,6 +80,7 @@ ld \- the GNU linker
.RB "[\|" \-r | \-Ur "\|]"
.RB "[\|" \-S "\|]"
.RB "[\|" \-s "\|]"
.RB "[\|" \-sort\-common "\|]"
.RB "[\|" "\-T\ "\c
.I commandfile\c
\&\|]
@ -99,6 +100,7 @@ ld \- the GNU linker
.RB "[\|" \-V "\|]"
.RB "[\|" \-v "\|]"
.RB "[\|" \-\-version "\|]"
.RB "[\|" \-warn\-common "\|]"
.RB "[\|" \-X "\|]"
.RB "[\|" \-x "\|]"
.ad b
@ -304,7 +306,7 @@ use will add another pair of name variants to search for when \c
specifies a library.
.TP
.BI "-b " "input-format"\c
.BI "\-b " "input-format"\c
\&
Specify the binary format for input object files that follow this option
on the command line. You don't usually need to specify this, as
@ -349,7 +351,7 @@ but has no effect on \c
\&.
.TP
.BI "-c " "commandfile"\c
.BI "\-c " "commandfile"\c
\&
Directs \c
.B ld\c
@ -448,12 +450,12 @@ but it accepts (and ignores) the \c
with scripts written to call the old linker.
.TP
.BI "-format " "input-format"\c
.BI "\-format " "input\-format"\c
\&
Synonym for \c
.B \-b\c
\& \c
.I input-format\c
.I input\-format\c
\&.
.TP
@ -483,7 +485,7 @@ Perform an incremental link (same as option \c
\&).
.TP
.BI "-l" "ar"\c
.BI "\-l" "ar"\c
\&
Add an archive file \c
.I ar\c
@ -501,7 +503,7 @@ path-list for occurrences of \c
specified.
.TP
.BI "-L" "searchdir"\c
.BI "\-L" "searchdir"\c
\&
This command adds path \c
.I searchdir\c
@ -576,13 +578,13 @@ sets the text segment to be read only, and \c
if possible.
.TP
.B \-noinhibit-exec
.B \-noinhibit\-exec
Normally, the linker will not produce an output file if it encounters
errors during the link process. With this flag, you can specify that
you wish the output file retained even after non-fatal errors.
.TP
.BI "-o " "output"\c
.BI "\-o " "output"\c
\&
.I output\c
\&
@ -599,7 +601,7 @@ script command \c
\& can also specify the output file name.
.TP
.BI "-oformat " "output-format"\c
.BI "\-oformat " "output\-format"\c
\&
Specify the binary format for the output object file.
You don't usually need to specify this, as
@ -615,7 +617,7 @@ The script command
can also specify the output format, but this option overrides it.
.TP
.BI "-R " "filename"\c
.BI "\-R " "filename"\c
\&
.I file\c
\&
@ -674,11 +676,20 @@ Omits debugger symbol information (but not all symbols) from the output file.
Omits all symbol information from the output file.
.TP
.BI "-Tbss " "org"\c
.B \-sort\-common
Normally, when
.B ld
places the global common symbols in the appropriate output sections,
it sorts them by size. First come all the one byte symbols, then all
the two bytes, then all the four bytes, and then everything else.
This option disables that sorting.
.TP
.BI "-Tdata " "org"\c
.BI "\-Tbss " "org"\c
.TP
.BI "-Ttext " "org"\c
.BI "\-Tdata " "org"\c
.TP
.BI "\-Ttext " "org"\c
Use \c
.I org\c
\& as the starting address for\(em\&respectively\(em\&the
@ -694,10 +705,10 @@ Use \c
\& must be a hexadecimal integer.
.TP
.BI "-T " "commandfile"\c
.BI "\-T " "commandfile"\c
\&
.TP
.BI "-T" "commandfile"\c
.BI "\-T" "commandfile"\c
Equivalent to \c
.B \-c \c
.I commandfile\c
@ -712,7 +723,7 @@ Prints names of input files as \c
\& processes them.
.TP
.BI "-u " "sym"
.BI "\-u " "sym"
Forces \c
.I sym\c
\& to be entered in the output file as an undefined symbol.
@ -758,6 +769,13 @@ Display the version number for \c
.B ld
and exit.
.TP
.B \-warn\-common
Warn when a common symbol is combined with another common symbol or with
a symbol definition. Unix linkers allow this somewhat sloppy practice,
but linkers on some other operating systems do not. This option allows
you to find potential problems from combining global symbols.
.TP
.B \-X
If \c

View file

@ -172,10 +172,10 @@ ld [ -o @var{output} ] @var{objfile}@dots{}
[ -l@var{archive} ] [ -L@var{searchdir} ] [ -M ] [ -Map @var{mapfile} ]
[ -m @var{emulation} ] [ -N | -n ] [ -noinhibit-exec ]
[ -oformat @var{output-format} ] [ -R @var{filename} ] [ -relax ]
[ -r | -Ur ] [ -S ] [ -s ] [ -T @var{commandfile} ]
[ -r | -Ur ] [ -S ] [ -s ] [ -sort-common ] [ -T @var{commandfile} ]
[ -Ttext @var{textorg} ] [ -Tdata @var{dataorg} ]
[ -Tbss @var{bssorg} ] [ -t ] [ -u @var{symbol}] [-V] [-v] [ --version ]
[ -y@var{symbol} ] [ -X ] [-x ]
[ -warn-common ] [ -y@var{symbol} ] [ -X ] [-x ]
@end smallexample
This plethora of command-line options may seem intimidating, but in
@ -508,6 +508,12 @@ Omit debugger symbol information (but not all symbols) from the output file.
@cindex strip all symbols
Omit all symbol information from the output file.
@item -sort-common
Normally, when @code{ld} places the global common symbols in the
appropriate output sections, it sorts them by size. First come all the
one byte symbols, then all the two bytes, then all the four bytes, and
then everything else. This option disables that sorting.
@item -Tbss @var{bssorg}
@kindex -Tbss @var{bssorg}
@itemx -Tdata @var{dataorg}
@ -575,6 +581,81 @@ Display the version number for @code{ld}.
@kindex --version
Display the version number for @code{ld} and exit.
@item -warn-common
Warn when a common symbol is combined with another common symbol or with
a symbol definition. Unix linkers allow this somewhat sloppy practice,
but linkers on some other operating systems do not. This option allows
you to find potential problems from combining global symbols.
There are three kinds of global symbols, illustrated here by C examples:
@table @samp
@item int i = 1;
A definition, which goes in the initialized data section of the output
file.
@item extern int i;
An undefined reference, which does not allocate space.
There must be either a definition or a common symbol for the
variable somewhere.
@item int i;
A common symbol. If there are only (one or more) common symbols for a
variable, it goes in the uninitialized data area of the output file.
The linker merges multiple common symbols for the same variable into a
single symbol. If they are of different sizes, it picks the largest
size. The linker turns a common symbol into a declaration, if there is
a definition of the same variable.
@end table
The @samp{-warn-common} option can produce five kinds of warnings. Each
warning consists of a pair of lines: the first describes the symbol just
encountered, and the second describes the previous symbol encountered
with the same name. One or both of the two symbols will be a common
symbol.
@enumerate
@item
Turning a common symbol into a reference, because there is already a
definition for the symbol.
@smallexample
@var{file}(@var{section}): warning: common of `@var{symbol}' overridden by definition
@var{file}(@var{section}): warning: defined here
@end smallexample
@item
Turning a common symbol into a reference, because a later definition for
the symbol is encountered. This is the same as the previous case,
except that the symbols are encountered in a different order.
@smallexample
@var{file}(@var{section}): warning: definition of `@var{symbol}' overriding common
@var{file}(@var{section}): warning: common is here
@end smallexample
@item
Merging a common symbol with a previous same-sized common symbol.
@smallexample
@var{file}(@var{section}): warning: multiple common of `@var{symbol}'
@var{file}(@var{section}): warning: previous common is here
@end smallexample
@item
Merging a common symbol with a previous larger common symbol.
@smallexample
@var{file}(@var{section}): warning: common of `@var{symbol}' overridden by larger common
@var{file}(@var{section}): warning: larger common is here
@end smallexample
@item
Merging a common symbol with a previous smaller common symbol. This is
the same as the previous case, except that the symbols are
encountered in a different order.
@smallexample
@var{file}(@var{section}): warning: common of `@var{symbol}' overriding smaller common
@var{file}(@var{section}): warning: smaller common is here
@end smallexample
@end enumerate
@item -X
@kindex -X
@cindex local symbols, deleting

View file

@ -29,8 +29,8 @@ This was written by steve chamberlain
#include "ldgram.h"
int ldgram_in_defsym;
int ldgram_had_equals;
int ldgram_in_script;
extern int ldgram_had_equals;
extern int ldgram_in_script;
int hex_mode;
extern int fgetc();
@ -107,6 +107,7 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
<COMMAND>"-oformat" { return OPTION_oformat; }
<COMMAND>"-sort-common" { return OPTION_sort_common;}
<COMMAND>"-sort_common" { return OPTION_sort_common;}
<COMMAND>"-warn-common" { return OPTION_warn_common;}
<COMMAND>"-n" { return OPTION_n; }
<COMMAND>"-N" { return OPTION_N; }
<COMMAND>"-r" { return OPTION_r; }
@ -143,8 +144,9 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
<COMMAND>"-L"{FILENAME} {
yylval.name = buystring(yytext+2);
return OPTION_L;
return OPTION_Lfile;
}
<COMMAND>"-L" { return OPTION_L; }
<COMMAND>"-Ttext" {
yylval.name = ".text";
return OPTION_Texp;
@ -202,6 +204,15 @@ NOCFILENAMECHAR [_a-zA-Z0-9\/\.\-\_\+\$\:\[\]\\\~]
yylval.integer = atoi (yytext + 2);
return OPTION_Gval;
}
<COMMAND>"-Qy" { return OPTION_Qy; }
<COMMAND>"-dn" { return OPTION_dn; }
<COMMAND>"-Y" { return OPTION_Y; }
<COMMAND>"-YP,"{FILENAME} {
yylval.name = buystring (yytext+4);
return OPTION_YP;
}
<MRI,EXPRESSION>"$"([0-9A-Fa-f])+ {
yylval.integer = strtoul(yytext+1, 0,16);
return INT;

View file

@ -170,14 +170,20 @@ main (argc, argv)
if (had_script == false)
{
/* Read the emulation's appropriate default script. */
char *scriptname = ldemul_get_script ();
/* sizeof counts the terminating NUL. */
size_t size = strlen (scriptname) + sizeof ("-T /ldscripts/");
char *buf = (char *) ldmalloc(size);
/* The initial slash prevents finding the script in `.' first. */
sprintf (buf, "-T /ldscripts/%s", scriptname);
parse_line (buf, 0);
free (buf);
int isfile;
char *s = ldemul_get_script (&isfile);
if (isfile)
{
/* sizeof counts the terminating NUL. */
size_t size = strlen (s) + sizeof ("-T ");
char *buf = (char *) ldmalloc(size);
sprintf (buf, "-T %s", s);
parse_line (buf, 0);
free (buf);
}
else
parse_line (s, 1);
}
if (config.relocateable_output && command_line.relax)
@ -490,23 +496,26 @@ enter_global_ref (nlist_p, name)
refize (sp, sp->scoms_chain);
sp->scoms_chain = 0;
}
}
else
{
if (bfd_is_com_section (sym->section))
{
/* If we have a definition of this symbol already then
this common turns into a reference. Also we only
ever point to the largest common, so if we
have a common, but it's bigger that the new symbol
the turn this into a reference too. */
this common turns into a reference. Also we only
ever point to the largest common, so if we
have a common, but it's bigger that the new symbol
the turn this into a reference too. */
if (sp->sdefs_chain)
{
/* This is a common symbol, but we already have a definition
for it, so just link it into the ref chain as if
it were a reference */
for it, so just link it into the ref chain as if
it were a reference */
if (config.warn_common)
multiple_warn("%C: warning: common of `%s' overridden by definition\n",
sym,
"%C: warning: defined here\n",
*(sp->sdefs_chain));
refize (sp, nlist_p);
}
else if (sp->scoms_chain)
@ -515,11 +524,29 @@ enter_global_ref (nlist_p, name)
if ((*(sp->scoms_chain))->value > sym->value)
{
/* other common is bigger, throw this one away */
if (config.warn_common)
multiple_warn("%C: warning: common of `%s' overridden by larger common\n",
sym,
"%C: warning: larger common is here\n",
*(sp->scoms_chain));
refize (sp, nlist_p);
}
else if (sp->scoms_chain != nlist_p)
{
/* other common is smaller, throw that away */
if (config.warn_common)
{
if ((*(sp->scoms_chain))->value < sym->value)
multiple_warn("%C: warning: common of `%s' overriding smaller common\n",
sym,
"%C: warning: smaller common is here\n",
*(sp->scoms_chain));
else
multiple_warn("%C: warning: multiple common of `%s'\n",
sym,
"%C: warning: previous common is here\n",
*(sp->scoms_chain));
}
refize (sp, sp->scoms_chain);
sp->scoms_chain = nlist_p;
}
@ -527,10 +554,9 @@ enter_global_ref (nlist_p, name)
else
{
/* This is the first time we've seen a common, so remember it
- if it was undefined before, we know it's defined now. If
the symbol has been marked as really being a constructor,
then treat this as a ref
*/
- if it was undefined before, we know it's defined now. If
the symbol has been marked as really being a constructor,
then treat this as a ref. */
if (sp->flags & SYM_CONSTRUCTOR)
{
/* Turn this into a ref */
@ -547,27 +573,17 @@ enter_global_ref (nlist_p, name)
}
}
}
else if (sym->section != &bfd_und_section)
{
/* This is the definition of a symbol, add to def chain */
if (sp->sdefs_chain && (*(sp->sdefs_chain))->section != sym->section)
{
/* Multiple definition */
asymbol *sy = *(sp->sdefs_chain);
lang_input_statement_type *stat =
(lang_input_statement_type *) bfd_asymbol_bfd (sy)->usrdata;
lang_input_statement_type *stat1 =
(lang_input_statement_type *) bfd_asymbol_bfd (sym)->usrdata;
asymbol **stat1_symbols = stat1 ? stat1->asymbols : 0;
asymbol **stat_symbols = stat ? stat->asymbols : 0;
multiple_warn("%X%C: multiple definition of `%s'\n",
sym,
"%X%C: first defined here\n",
*(sp->sdefs_chain));
multiple_def_count++;
einfo ("%X%C: multiple definition of `%T'\n",
bfd_asymbol_bfd (sym), sym->section, stat1_symbols, sym->value, sym);
einfo ("%X%C: first seen here\n",
bfd_asymbol_bfd (sy), sy->section, stat_symbols, sy->value);
}
else
{
@ -577,6 +593,11 @@ enter_global_ref (nlist_p, name)
/* A definition overrides a common symbol */
if (sp->scoms_chain)
{
if (config.warn_common)
multiple_warn("%C: warning: definition of `%s' overriding common\n",
sym,
"%C: warning: common is here\n",
*(sp->scoms_chain));
refize (sp, sp->scoms_chain);
sp->scoms_chain = 0;
commons_pending--;
@ -595,7 +616,6 @@ enter_global_ref (nlist_p, name)
{
/* And it's the first time we've seen it */
undefined_global_sym_count++;
}
refize (sp, nlist_p);

View file

@ -87,6 +87,7 @@ vfinfo(fp, fmt, arg)
va_list arg;
{
boolean fatal = false;
while (*fmt)
{
while (*fmt != '%' && *fmt != '\0')
@ -94,6 +95,7 @@ vfinfo(fp, fmt, arg)
putc(*fmt, fp);
fmt++;
}
if (*fmt == '%')
{
fmt ++;
@ -102,12 +104,14 @@ vfinfo(fp, fmt, arg)
case 'X':
config.make_executable = false;
break;
case 'V':
{
bfd_vma value = va_arg(arg, bfd_vma);
fprintf_vma(fp, value);
}
{
bfd_vma value = va_arg(arg, bfd_vma);
fprintf_vma(fp, value);
}
break;
case 'v':
{
char buf[100];
@ -121,13 +125,12 @@ vfinfo(fp, fmt, arg)
fputs (p, fp);
}
break;
case 'T':
{
asymbol *symbol = va_arg(arg, asymbol *);
if (symbol)
{
asection *section = symbol->section;
char *cplusname = demangle(symbol->name, 1);
CONST char *section_name = section->name;
@ -146,6 +149,7 @@ vfinfo(fp, fmt, arg)
}
}
break;
case 'B':
{
bfd *abfd = va_arg(arg, bfd *);
@ -155,24 +159,23 @@ vfinfo(fp, fmt, arg)
}
else {
fprintf(fp,"%s", abfd->filename);
}
}
break;
case 'F':
fatal = true;
break;
case 'P':
fprintf(fp,"%s", program_name);
break;
case 'E':
/* Replace with the most recent errno explanation */
fprintf(fp, bfd_errmsg(bfd_error));
break;
case 'I':
{
lang_input_statement_type *i =
@ -181,12 +184,10 @@ vfinfo(fp, fmt, arg)
fprintf(fp,"%s", i->local_sym_name);
}
break;
case 'S':
/* Print source script file and line number */
{
extern unsigned int lineno;
if (ldfile_input_filename == (char *)NULL) {
fprintf(fp,"command line");
@ -195,7 +196,6 @@ vfinfo(fp, fmt, arg)
fprintf(fp,"%s:%u", ldfile_input_filename, lineno );
}
}
break;
case 'R':
@ -210,9 +210,6 @@ vfinfo(fp, fmt, arg)
}
break;
case 'C':
{
CONST char *filename;
@ -237,8 +234,7 @@ vfinfo(fp, fmt, arg)
filename = abfd->filename;
if (functionname != (char *)NULL)
{
/* There is no initial '_' to remove here. */
cplus_name = demangle(functionname, 0);
cplus_name = demangle(functionname, 1);
fprintf(fp,"%s:%u: (%s)", filename, linenumber, cplus_name);
}
@ -256,15 +252,18 @@ vfinfo(fp, fmt, arg)
case 's':
fprintf(fp,"%s", va_arg(arg, char *));
break;
case 'd':
fprintf(fp,"%d", va_arg(arg, int));
break;
default:
fprintf(fp,"%s", va_arg(arg, char *));
break;
}
}
}
if (fatal == true)
{
extern char *output_filename;
@ -308,10 +307,39 @@ va_dcl
va_end(arg);
}
/* Warn about a symbol NEWSYM being multiply defined with another symbol OLDSYM.
MESSAGE1 and MESSAGE2 should look something like:
"%C: warning: multiple commons of `%s'\n"
"%C: warning: previous common here\n" */
void
multiple_warn (message1, newsym, message2, oldsym)
char *message1;
asymbol *newsym;
char *message2;
asymbol *oldsym;
{
lang_input_statement_type *stat;
asymbol **stat_symbols;
stat = (lang_input_statement_type *) bfd_asymbol_bfd (newsym)->usrdata;
stat_symbols = stat ? stat->asymbols : 0;
einfo (message1,
bfd_asymbol_bfd (newsym), newsym->section, stat_symbols, newsym->value,
demangle (newsym->name, 1));
stat = (lang_input_statement_type *) bfd_asymbol_bfd (oldsym)->usrdata;
stat_symbols = stat ? stat->asymbols : 0;
einfo (message2,
bfd_asymbol_bfd (oldsym), oldsym->section, stat_symbols, oldsym->value);
}
void
info_assert(file, line)
char *file;
unsigned int line;
char *file;
unsigned int line;
{
einfo("%F%P internal error %s %d\n", file,line);
}