* object.h (Merged_symbol_value::value): Do our best to handle a
	negative addend.
This commit is contained in:
Ian Lance Taylor 2008-07-24 01:24:50 +00:00
parent 94c16cb988
commit 7f649c59d1
2 changed files with 30 additions and 3 deletions

View File

@ -1,5 +1,9 @@
2008-07-23 Ian Lance Taylor <iant@google.com>
PR 6658
* object.h (Merged_symbol_value::value): Do our best to handle a
negative addend.
PR 6647
* script.cc (Version_script_info::get_versions): Don't add empty
version tag to return value.

View File

@ -822,13 +822,36 @@ class Merged_symbol_value
Value
value(const Relobj* object, unsigned int input_shndx, Value addend) const
{
Value input_offset = this->input_value_ + addend;
// This is a relocation against a section symbol. ADDEND is the
// offset in the section. The result should be the start of some
// merge area. If the object file wants something else, it should
// use a regular symbol rather than a section symbol.
// Unfortunately, PR 6658 shows a case in which the object file
// refers to the section symbol, but uses a negative ADDEND to
// compensate for a PC relative reloc. We can't handle the
// general case. However, we can handle the special case of a
// negative addend, by assuming that it refers to the start of the
// section. Of course, that means that we have to guess when
// ADDEND is negative. It is normal to see a 32-bit value here
// even when the template parameter size is 64, as 64-bit object
// file formats have 32-bit relocations. We know this is a merge
// section, so we know it has to fit into memory. So we assume
// that we won't see a value larger than a large 32-bit unsigned
// value. This will break objects with very very large merge
// sections; they probably break in other ways anyhow.
Value input_offset = this->input_value_;
if (addend < 0xffffff00)
{
input_offset += addend;
addend = 0;
}
typename Output_addresses::const_iterator p =
this->output_addresses_.find(input_offset);
if (p != this->output_addresses_.end())
return p->second;
return p->second + addend;
return this->value_from_output_section(object, input_shndx, input_offset);
return (this->value_from_output_section(object, input_shndx, input_offset)
+ addend);
}
private: