Index: binutils/gold/resolve.cc |
diff --git a/binutils/gold/resolve.cc b/binutils/gold/resolve.cc |
index 82af9b4c6e83afc800cc6932185a3f573a8ea235..2f0479ac85c65f73ecb4e81a3fd1d55fc645a18f 100644 |
--- a/binutils/gold/resolve.cc |
+++ b/binutils/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. |