aboutsummaryrefslogtreecommitdiff
path: root/gold/resolve.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gold/resolve.cc')
-rw-r--r--gold/resolve.cc93
1 files changed, 78 insertions, 15 deletions
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.