aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2009-11-04 01:24:41 +0000
committerIan Lance Taylor <ian@airs.com>2009-11-04 01:24:41 +0000
commit1ae4d23b731a2a5fa5d688bc255d52e7f1eb9232 (patch)
treef35dae3b6a4203d8c2cc52a25d3f23c5188db707
parent690a96ed8ce0d2256eec357a187252a0974241af (diff)
downloadbinutils-1ae4d23b731a2a5fa5d688bc255d52e7f1eb9232.zip
binutils-1ae4d23b731a2a5fa5d688bc255d52e7f1eb9232.tar.gz
binutils-1ae4d23b731a2a5fa5d688bc255d52e7f1eb9232.tar.bz2
PR 10860
* options.h (class General_options): Add --warn-common. * resolve.cc (Symbol_table::resolve): Handle --warn-common when merging two common symbols. (Symbol_table::should_override): Handle --warn-common when merging a common symbol with a defined symbol. Use report_resolve_problem for multiple definitions. (Symbol_table::report_resolve_problem): New function. * symtab.h (class Symbol_table): Declare report_resolve_problem.
-rw-r--r--gold/ChangeLog12
-rw-r--r--gold/options.h4
-rw-r--r--gold/resolve.cc93
-rw-r--r--gold/symtab.h5
4 files changed, 99 insertions, 15 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index e9d9e9c..6a7d5e7 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,15 @@
+2009-11-03 Ian Lance Taylor <iant@google.com>
+
+ PR 10860
+ * options.h (class General_options): Add --warn-common.
+ * resolve.cc (Symbol_table::resolve): Handle --warn-common when
+ merging two common symbols.
+ (Symbol_table::should_override): Handle --warn-common when merging
+ a common symbol with a defined symbol. Use report_resolve_problem
+ for multiple definitions.
+ (Symbol_table::report_resolve_problem): New function.
+ * symtab.h (class Symbol_table): Declare report_resolve_problem.
+
2009-11-03 Doug Kwan <dougkwan@google.com>
* arm.cc (Target_arm::Target_arm): Initialize stub_tables_ and
diff --git a/gold/options.h b/gold/options.h
index c1d5329..399c301 100644
--- a/gold/options.h
+++ b/gold/options.h
@@ -918,6 +918,10 @@ class General_options
DEFINE_special(version_script, options::TWO_DASHES, '\0',
N_("Read version script"), N_("FILE"));
+ DEFINE_bool(warn_common, options::TWO_DASHES, '\0', false,
+ N_("Warn about duplicate common symbols"),
+ N_("Do not warn about duplicate common symbols (default)"));
+
DEFINE_bool(warn_constructors, options::TWO_DASHES, '\0', false,
N_("Ignored"), N_("Ignored"));
diff --git a/gold/resolve.cc b/gold/resolve.cc
index 82af9b4..2f0479a 100644
--- a/gold/resolve.cc
+++ b/gold/resolve.cc
@@ -302,25 +302,41 @@ Symbol_table::resolve(Sized_symbol<size>* to,
sym.get_st_type());
bool adjust_common_sizes;
+ typename Sized_symbol<size>::Size_type tosize = to->symsize();
if (Symbol_table::should_override(to, frombits, object,
&adjust_common_sizes))
{
- typename Sized_symbol<size>::Size_type tosize = to->symsize();
-
this->override(to, sym, st_shndx, is_ordinary, object, version);
-
if (adjust_common_sizes && tosize > to->symsize())
to->set_symsize(tosize);
}
else
{
- if (adjust_common_sizes && sym.get_st_size() > to->symsize())
+ if (adjust_common_sizes && sym.get_st_size() > tosize)
to->set_symsize(sym.get_st_size());
// The ELF ABI says that even for a reference to a symbol we
// merge the visibility.
to->override_visibility(sym.get_st_visibility());
}
+ if (adjust_common_sizes && parameters->options().warn_common())
+ {
+ if (tosize > sym.get_st_size())
+ Symbol_table::report_resolve_problem(false,
+ _("common of '%s' overriding "
+ "smaller common"),
+ to, object);
+ else if (tosize < sym.get_st_size())
+ Symbol_table::report_resolve_problem(false,
+ _("common of '%s' overidden by "
+ "larger common"),
+ to, object);
+ else
+ Symbol_table::report_resolve_problem(false,
+ _("multiple common of '%s'"),
+ to, object);
+ }
+
// A new weak undefined reference, merging with an old weak
// reference, could be a One Definition Rule (ODR) violation --
// especially if the types or sizes of the references differ. We'll
@@ -422,14 +438,9 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
|| object->just_symbols())
return false;
- // FIXME: Do a better job of reporting locations.
- gold_error(_("%s: multiple definition of %s"),
- object != NULL ? object->name().c_str() : _("command line"),
- to->demangled_name().c_str());
- gold_error(_("%s: previous definition here"),
- (to->source() == Symbol::FROM_OBJECT
- ? to->object()->name().c_str()
- : _("command line")));
+ Symbol_table::report_resolve_problem(true,
+ _("multiple definition of '%s'"),
+ to, object);
return false;
case WEAK_DEF * 16 + DEF:
@@ -464,8 +475,12 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
case DYN_COMMON * 16 + DEF:
case DYN_WEAK_COMMON * 16 + DEF:
// We've seen a common symbol and now we see a definition. The
- // definition overrides. FIXME: We should optionally issue, version a
- // warning.
+ // definition overrides.
+ if (parameters->options().warn_common())
+ Symbol_table::report_resolve_problem(false,
+ _("definition of '%s' overriding "
+ "common"),
+ to, object);
return true;
case DEF * 16 + WEAK_DEF:
@@ -495,7 +510,12 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
case DYN_COMMON * 16 + WEAK_DEF:
case DYN_WEAK_COMMON * 16 + WEAK_DEF:
// A weak definition does override a definition in a dynamic
- // object. FIXME: We should optionally issue a warning.
+ // object.
+ if (parameters->options().warn_common())
+ Symbol_table::report_resolve_problem(false,
+ _("definition of '%s' overriding "
+ "dynamic common definition"),
+ to, object);
return true;
case DEF * 16 + DYN_DEF:
@@ -611,6 +631,11 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
case DEF * 16 + COMMON:
// A common symbol does not override a definition.
+ if (parameters->options().warn_common())
+ Symbol_table::report_resolve_problem(false,
+ _("common '%s' overridden by "
+ "previous definition"),
+ to, object);
return false;
case WEAK_DEF * 16 + COMMON:
@@ -716,6 +741,44 @@ Symbol_table::should_override(const Symbol* to, unsigned int frombits,
}
}
+// Issue an error or warning due to symbol resolution. IS_ERROR
+// indicates an error rather than a warning. MSG is the error
+// message; it is expected to have a %s for the symbol name. TO is
+// the existing symbol. OBJECT is where the new symbol was found.
+
+// FIXME: We should have better location information here. When the
+// symbol is defined, we should be able to pull the location from the
+// debug info if there is any.
+
+void
+Symbol_table::report_resolve_problem(bool is_error, const char* msg,
+ const Symbol* to, Object* object)
+{
+ std::string demangled(to->demangled_name());
+ size_t len = strlen(msg) + demangled.length() + 10;
+ char* buf = new char[len];
+ snprintf(buf, len, msg, demangled.c_str());
+
+ const char* objname;
+ if (object != NULL)
+ objname = object->name().c_str();
+ else
+ objname = _("command line");
+
+ if (is_error)
+ gold_error("%s: %s", objname, buf);
+ else
+ gold_warning("%s: %s", objname, buf);
+
+ delete[] buf;
+
+ if (to->source() == Symbol::FROM_OBJECT)
+ objname = to->object()->name().c_str();
+ else
+ objname = _("command line");
+ gold_info("%s: %s: previous definition here", program_name, objname);
+}
+
// A special case of should_override which is only called for a strong
// defined symbol from a regular object file. This is used when
// defining special symbols.
diff --git a/gold/symtab.h b/gold/symtab.h
index d1cd647..544712d 100644
--- a/gold/symtab.h
+++ b/gold/symtab.h
@@ -1488,6 +1488,11 @@ class Symbol_table
static bool
should_override(const Symbol*, unsigned int, Object*, bool*);
+ // Report a problem in symbol resolution.
+ static void
+ report_resolve_problem(bool is_error, const char* msg, const Symbol* to,
+ Object* object);
+
// Override a symbol.
template<int size, bool big_endian>
void