{
typedef typename elfcpp::Swap<32, false>::Valtype Valtype;
Valtype* wv = reinterpret_cast<Valtype*>(view);
- typename elfcpp::Elf_types<64>::Elf_Addr value =
- psymval->value(object, addend) - address;
+ typename elfcpp::Elf_types<64>::Elf_Addr value;
+ if (addend >= 0)
+ value = psymval->value(object, addend);
+ else
+ {
+ // For negative addends, get the symbol value without
+ // the addend, then add the addend using 64-bit arithmetic.
+ value = psymval->value(object, 0);
+ value += addend;
+ }
+ value -= address;
elfcpp::Swap<32, false>::writeval(wv, value);
return (Bits<32>::has_overflow(value)
? Base::RELOC_OVERFLOW : Base::RELOC_OK);
}
if (rstatus == Reloc_funcs::RELOC_OVERFLOW)
- gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
- _("relocation overflow"));
+ {
+ if (gsym == NULL)
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
+ gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
+ _("relocation overflow: "
+ "reference to local symbol %u in %s"),
+ r_sym, object->name().c_str());
+ }
+ else if (gsym->is_defined() && gsym->source() == Symbol::FROM_OBJECT)
+ {
+ gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
+ _("relocation overflow: "
+ "reference to '%s' defined in %s"),
+ gsym->name(),
+ gsym->object()->name().c_str());
+ }
+ else
+ {
+ gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
+ _("relocation overflow: reference to '%s'"),
+ gsym->name());
+ }
+ }
return true;
}