+ output_dynsym_index() const
+ {
+ gold_assert(this->output_dynsym_index_ != 0
+ && this->output_dynsym_index_ != -1U);
+ return this->output_dynsym_index_;
+ }
+
+ // Set the index of the input section in the input file.
+ void
+ set_input_shndx(unsigned int i, bool is_ordinary)
+ {
+ this->input_shndx_ = i;
+ // input_shndx_ field is a bitfield, so make sure that the value
+ // fits.
+ gold_assert(this->input_shndx_ == i);
+ this->is_ordinary_shndx_ = is_ordinary;
+ }
+
+ // Return the index of the input section in the input file.
+ unsigned int
+ input_shndx(bool* is_ordinary) const
+ {
+ *is_ordinary = this->is_ordinary_shndx_;
+ return this->input_shndx_;
+ }
+
+ // Whether this is a section symbol.
+ bool
+ is_section_symbol() const
+ { return this->is_section_symbol_; }
+
+ // Record that this is a section symbol.
+ void
+ set_is_section_symbol()
+ {
+ gold_assert(!this->needs_output_dynsym_entry());
+ this->is_section_symbol_ = true;
+ }
+
+ // Record that this is a TLS symbol.
+ void
+ set_is_tls_symbol()
+ { this->is_tls_symbol_ = true; }
+
+ // Return true if this is a TLS symbol.
+ bool
+ is_tls_symbol() const
+ { return this->is_tls_symbol_; }
+
+ // Record that this is an IFUNC symbol.
+ void
+ set_is_ifunc_symbol()
+ { this->is_ifunc_symbol_ = true; }
+
+ // Return true if this is an IFUNC symbol.
+ bool
+ is_ifunc_symbol() const
+ { return this->is_ifunc_symbol_; }
+
+ // Return true if this has output value.
+ bool
+ has_output_value() const
+ { return this->has_output_value_; }
+
+ private:
+ // The index of this local symbol in the output symbol table. This
+ // will be 0 if no value has been assigned yet, and the symbol may
+ // be omitted. This will be -1U if the symbol should not go into
+ // the symbol table. This will be -2U if the symbol must go into
+ // the symbol table, but no index has been assigned yet.
+ unsigned int output_symtab_index_;
+ // The index of this local symbol in the dynamic symbol table. This
+ // will be -1U if the symbol should not go into the symbol table.
+ unsigned int output_dynsym_index_;
+ // The section index in the input file in which this symbol is
+ // defined.
+ unsigned int input_shndx_ : 27;
+ // Whether the section index is an ordinary index, not a special
+ // value.
+ bool is_ordinary_shndx_ : 1;
+ // Whether this is a STT_SECTION symbol.
+ bool is_section_symbol_ : 1;
+ // Whether this is a STT_TLS symbol.
+ bool is_tls_symbol_ : 1;
+ // Whether this is a STT_GNU_IFUNC symbol.
+ bool is_ifunc_symbol_ : 1;
+ // Whether this symbol has a value for the output file. This is
+ // normally set to true during Layout::finalize, by
+ // finalize_local_symbols. It will be false for a section symbol in
+ // a merge section, as for such symbols we can not determine the
+ // value to use in a relocation until we see the addend.
+ bool has_output_value_ : 1;
+ union
+ {
+ // This is used if has_output_value_ is true. Between
+ // count_local_symbols and finalize_local_symbols, this is the
+ // value in the input file. After finalize_local_symbols, it is
+ // the value in the output file.
+ Value value;
+ // This is used if has_output_value_ is false. It points to the
+ // information we need to get the value for a merge section.
+ Merged_symbol_value<size>* merged_symbol_value;
+ } u_;
+};
+
+// This type is used to modify relocations for -fsplit-stack. It is
+// indexed by relocation index, and means that the relocation at that
+// index should use the symbol from the vector, rather than the one
+// indicated by the relocation.
+
+class Reloc_symbol_changes
+{
+ public:
+ Reloc_symbol_changes(size_t count)
+ : vec_(count, NULL)
+ { }
+
+ void
+ set(size_t i, Symbol* sym)
+ { this->vec_[i] = sym; }
+
+ const Symbol*
+ operator[](size_t i) const
+ { return this->vec_[i]; }
+
+ private:
+ std::vector<Symbol*> vec_;
+};
+
+// Type for mapping section index to uncompressed size and contents.
+
+struct Compressed_section_info
+{
+ section_size_type size;
+ const unsigned char* contents;
+};
+typedef std::map<unsigned int, Compressed_section_info> Compressed_section_map;
+
+// Abstract base class for a regular object file, either a real object file
+// or an incremental (unchanged) object. This is size and endian specific.
+
+template<int size, bool big_endian>
+class Sized_relobj : public Relobj
+{
+ public:
+ typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+ typedef Relobj::Symbols Symbols;
+
+ static const Address invalid_address = static_cast<Address>(0) - 1;
+
+ Sized_relobj(const std::string& name, Input_file* input_file)
+ : Relobj(name, input_file), local_got_offsets_(), section_offsets_()
+ { }
+
+ Sized_relobj(const std::string& name, Input_file* input_file,
+ off_t offset)
+ : Relobj(name, input_file, offset), local_got_offsets_(), section_offsets_()
+ { }
+
+ ~Sized_relobj()
+ { }
+
+ // If this is a regular object, return a pointer to the Sized_relobj_file
+ // object. Otherwise, return NULL.
+ virtual Sized_relobj_file<size, big_endian>*
+ sized_relobj()
+ { return NULL; }
+
+ const virtual Sized_relobj_file<size, big_endian>*
+ sized_relobj() const
+ { return NULL; }
+
+ // Checks if the offset of input section SHNDX within its output
+ // section is invalid.
+ bool
+ is_output_section_offset_invalid(unsigned int shndx) const
+ { return this->get_output_section_offset(shndx) == invalid_address; }
+
+ // Get the offset of input section SHNDX within its output section.
+ // This is -1 if the input section requires a special mapping, such
+ // as a merge section. The output section can be found in the
+ // output_sections_ field of the parent class Relobj.
+ Address
+ get_output_section_offset(unsigned int shndx) const
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ return this->section_offsets_[shndx];
+ }
+
+ // Iterate over local symbols, calling a visitor class V for each GOT offset
+ // associated with a local symbol.
+ void
+ do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
+
+ protected:
+ typedef Relobj::Output_sections Output_sections;
+
+ // Clear the local symbol information.
+ void
+ clear_got_offsets()
+ { this->local_got_offsets_.clear(); }
+
+ // Return the vector of section offsets.
+ std::vector<Address>&
+ section_offsets()
+ { return this->section_offsets_; }
+
+ // Get the address of an output section.
+ uint64_t
+ do_output_section_address(unsigned int shndx);
+
+ // Get the offset of a section.
+ uint64_t
+ do_output_section_offset(unsigned int shndx) const
+ {
+ Address off = this->get_output_section_offset(shndx);
+ if (off == invalid_address)
+ return -1ULL;
+ return off;
+ }
+
+ // Set the offset of a section.
+ void
+ do_set_section_offset(unsigned int shndx, uint64_t off)
+ {
+ gold_assert(shndx < this->section_offsets_.size());
+ this->section_offsets_[shndx] =
+ (off == static_cast<uint64_t>(-1)
+ ? invalid_address
+ : convert_types<Address, uint64_t>(off));
+ }
+
+ // Return whether the local symbol SYMNDX has a GOT offset of type
+ // GOT_TYPE.
+ bool
+ do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ {
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ return (p != this->local_got_offsets_.end()
+ && p->second->get_offset(got_type) != -1U);
+ }
+
+ // Return the GOT offset of type GOT_TYPE of the local symbol
+ // SYMNDX.
+ unsigned int
+ do_local_got_offset(unsigned int symndx, unsigned int got_type) const