From 7f649c59d1863d01c97a920232f86fdacaac2199 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 24 Jul 2008 01:24:50 +0000 Subject: [PATCH] PR 6658 * object.h (Merged_symbol_value::value): Do our best to handle a negative addend. --- gold/ChangeLog | 4 ++++ gold/object.h | 29 ++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index dca8a51e3d0..a1458995d30 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,9 @@ 2008-07-23 Ian Lance Taylor + 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. diff --git a/gold/object.h b/gold/object.h index 7334492fb23..8ddd68970a3 100644 --- a/gold/object.h +++ b/gold/object.h @@ -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: -- 2.30.2