diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/object.cc | 26 | ||||
-rw-r--r-- | gold/object.h | 26 |
2 files changed, 41 insertions, 11 deletions
diff --git a/gold/object.cc b/gold/object.cc index 2dbd0f2..9986383 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -586,6 +586,9 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, unsigned int shndx = sym.get_st_shndx(); lv.set_input_shndx(shndx); + if (sym.get_st_type() == elfcpp::STT_SECTION) + lv.set_is_section_symbol(); + if (shndx >= elfcpp::SHN_LORESERVE) { if (shndx == elfcpp::SHN_ABS) @@ -660,12 +663,14 @@ Sized_relobj<size, big_endian>::do_finalize_local_symbols(unsigned int index, } // Return the value of a local symbol defined in input section SHNDX, -// with value VALUE, adding addend ADDEND. This handles SHF_MERGE -// sections. +// with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL +// indicates whether the symbol is a section symbol. This handles +// SHF_MERGE sections. template<int size, bool big_endian> typename elfcpp::Elf_types<size>::Elf_Addr Sized_relobj<size, big_endian>::local_value(unsigned int shndx, Address value, + bool is_section_symbol, Address addend) const { const std::vector<Map_to_output>& mo(this->map_to_output()); @@ -673,7 +678,22 @@ Sized_relobj<size, big_endian>::local_value(unsigned int shndx, if (os == NULL) return addend; gold_assert(mo[shndx].offset == -1); - return os->output_address(this, shndx, value + addend); + + // Do the mapping required by the output section. If this is not a + // section symbol, then we want to map the symbol value, and then + // include the addend. If this is a section symbol, then we need to + // include the addend to figure out where in the section we are, + // before we do the mapping. This will do the right thing provided + // the assembler is careful to only convert a relocation in a merged + // section to a section symbol if there is a zero addend. If the + // assembler does not do this, then in general we can't know what to + // do, because we can't distinguish the addend for the instruction + // format from the addend for the section offset. + + if (is_section_symbol) + return os->output_address(this, shndx, value + addend); + else + return addend + os->output_address(this, shndx, value); } // Write out the local symbols. diff --git a/gold/object.h b/gold/object.h index cc1d5b2..e4359ac 100644 --- a/gold/object.h +++ b/gold/object.h @@ -487,8 +487,8 @@ class Symbol_value typedef typename elfcpp::Elf_types<size>::Elf_Addr Value; Symbol_value() - : output_symtab_index_(0), input_shndx_(0), needs_output_address_(false), - value_(0) + : output_symtab_index_(0), input_shndx_(0), is_section_symbol_(false), + needs_output_address_(false), value_(0) { } // Get the value of this symbol. OBJECT is the object in which this @@ -499,7 +499,8 @@ class Symbol_value { if (!this->needs_output_address_) return this->value_ + addend; - return object->local_value(this->input_shndx_, this->value_, addend); + return object->local_value(this->input_shndx_, this->value_, + this->is_section_symbol_, addend); } // Set the value of this symbol in the output symbol table. @@ -560,16 +561,23 @@ class Symbol_value set_input_shndx(unsigned int i) { this->input_shndx_ = i; } + // Record that this is a section symbol. + void + set_is_section_symbol() + { this->is_section_symbol_ = true; } + private: // The index of this local symbol in the output symbol table. This // will be -1 if the symbol should not go into the symbol table. unsigned int output_symtab_index_; // The section index in the input file in which this symbol is // defined. - unsigned int input_shndx_ : 31; + unsigned int input_shndx_ : 30; + // Whether this is a STT_SECTION symbol. + bool is_section_symbol_ : 1; // Whether getting the value of this symbol requires calling an // Output_section method. For example, this will be true of a - // STT_SECTION symbol in a SHF_MERGE section. + // symbol in a SHF_MERGE section. bool needs_output_address_ : 1; // The value of the symbol. If !needs_output_address_, this is the // value in the output file. If needs_output_address_, this is the @@ -660,10 +668,12 @@ class Sized_relobj : public Relobj } // Return the value of a local symbol define in input section SHNDX, - // with value VALUE, adding addend ADDEND. This handles SHF_MERGE - // sections. + // with value VALUE, adding addend ADDEND. IS_SECTION_SYMBOL + // indicates whether the symbol is a section symbol. This handles + // SHF_MERGE sections. Address - local_value(unsigned int shndx, Address value, Address addend) const; + local_value(unsigned int shndx, Address value, bool is_section_symbol, + Address addend) const; private: // For convenience. |