// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2016 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
Got_offset_list* got_next_;
};
+// The Local_got_entry_key used to index the GOT offsets for local
+// non-TLS symbols, and tp-relative offsets for TLS symbols.
+
+class Local_got_entry_key
+{
+ public:
+ Local_got_entry_key(unsigned int symndx, uint64_t addend)
+ : symndx_(symndx), addend_(addend)
+ {}
+
+ // Whether this equals to another Local_got_entry_key.
+ bool
+ eq(const Local_got_entry_key& key) const
+ {
+ return (this->symndx_ == key.symndx_ && this->addend_ == key.addend_);
+ }
+
+ // Compute a hash value for this using 64-bit FNV-1a hash.
+ size_t
+ hash_value() const
+ {
+ uint64_t h = 14695981039346656037ULL; // FNV offset basis.
+ uint64_t prime = 1099511628211ULL;
+ h = (h ^ static_cast<uint64_t>(this->symndx_)) * prime;
+ h = (h ^ static_cast<uint64_t>(this->addend_)) * prime;
+ return h;
+ }
+
+ // Functors for associative containers.
+ struct equal_to
+ {
+ bool
+ operator()(const Local_got_entry_key& key1,
+ const Local_got_entry_key& key2) const
+ { return key1.eq(key2); }
+ };
+
+ struct hash
+ {
+ size_t
+ operator()(const Local_got_entry_key& key) const
+ { return key.hash_value(); }
+ };
+
+ private:
+ // The local symbol index.
+ unsigned int symndx_;
+ // The addend.
+ uint64_t addend_;
+};
+
// Type for mapping section index to uncompressed size and contents.
struct Compressed_section_info
get_incremental_reloc_count(unsigned int symndx) const
{ return this->do_get_incremental_reloc_count(symndx); }
+ // Return the output view for section SHNDX.
+ unsigned char*
+ get_output_view(unsigned int shndx, section_size_type* plen) const
+ { return this->do_get_output_view(shndx, plen); }
+
protected:
// Returns NULL for Objects that are not dynamic objects. This method
// is overridden in the Dynobj class.
do_get_incremental_reloc_count(unsigned int) const
{ gold_unreachable(); }
+ // Return the output view for a section.
+ virtual unsigned char*
+ do_get_output_view(unsigned int, section_size_type*) const
+ { gold_unreachable(); }
+
void
set_compressed_sections(Compressed_section_map* compressed_sections)
{ this->compressed_sections_ = compressed_sections; }
// GOT_TYPE.
bool
local_has_got_offset(unsigned int symndx, unsigned int got_type) const
- { return this->do_local_has_got_offset(symndx, got_type); }
+ { return this->do_local_has_got_offset(symndx, got_type, 0); }
+
+ // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
+ // of type GOT_TYPE.
+ bool
+ local_has_got_offset(unsigned int symndx, unsigned int got_type,
+ uint64_t addend) const
+ { return this->do_local_has_got_offset(symndx, got_type, addend); }
// Return the GOT offset of type GOT_TYPE of the local symbol
// SYMNDX. It is an error to call this if the symbol does not have
// a GOT offset of the specified type.
unsigned int
local_got_offset(unsigned int symndx, unsigned int got_type) const
- { return this->do_local_got_offset(symndx, got_type); }
+ { return this->do_local_got_offset(symndx, got_type, 0); }
+
+ // Return the GOT offset of type GOT_TYPE of the local symbol
+ // SYMNDX plus ADDEND. It is an error to call this if the symbol
+ // does not have a GOT offset of the specified type.
+ unsigned int
+ local_got_offset(unsigned int symndx, unsigned int got_type,
+ uint64_t addend) const
+ { return this->do_local_got_offset(symndx, got_type, addend); }
// Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
// to GOT_OFFSET.
void
set_local_got_offset(unsigned int symndx, unsigned int got_type,
unsigned int got_offset)
- { this->do_set_local_got_offset(symndx, got_type, got_offset); }
+ { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); }
+
+ // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+ // plus ADDEND to GOT_OFFSET.
+ void
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset, uint64_t addend)
+ { this->do_set_local_got_offset(symndx, got_type, got_offset, addend); }
// Return whether the local symbol SYMNDX is a TLS symbol.
bool
virtual unsigned int
do_local_plt_offset(unsigned int symndx) const = 0;
- // Return whether a local symbol has a GOT offset of a given type.
+ // Return whether a local symbol plus addend has a GOT offset
+ // of a given type.
virtual bool
do_local_has_got_offset(unsigned int symndx,
- unsigned int got_type) const = 0;
+ unsigned int got_type, uint64_t addend) const = 0;
- // Return the GOT offset of a given type of a local symbol.
+ // Return the GOT offset of a given type of a local symbol plus addend.
virtual unsigned int
- do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+ do_local_got_offset(unsigned int symndx, unsigned int got_type,
+ uint64_t addend) const = 0;
- // Set the GOT offset with a given type for a local symbol.
+ // Set the GOT offset with a given type for a local symbol plus addend.
virtual void
do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
- unsigned int got_offset) = 0;
+ unsigned int got_offset, uint64_t addend) = 0;
// Return whether local symbol SYMNDX is a TLS symbol.
virtual bool
: convert_types<Address, uint64_t>(off));
}
- // Return whether the local symbol SYMNDX has a GOT offset of type
- // GOT_TYPE.
+ // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
+ // of type GOT_TYPE.
bool
- do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+ do_local_has_got_offset(unsigned int symndx, unsigned int got_type,
+ uint64_t addend) const
{
+ Local_got_entry_key key(symndx, addend);
Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
+ this->local_got_offsets_.find(key);
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.
+ // SYMNDX plus ADDEND.
unsigned int
- do_local_got_offset(unsigned int symndx, unsigned int got_type) const
+ do_local_got_offset(unsigned int symndx, unsigned int got_type,
+ uint64_t addend) const
{
+ Local_got_entry_key key(symndx, addend);
Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
+ this->local_got_offsets_.find(key);
gold_assert(p != this->local_got_offsets_.end());
unsigned int off = p->second->get_offset(got_type);
gold_assert(off != -1U);
}
// Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
- // to GOT_OFFSET.
+ // plus ADDEND to GOT_OFFSET.
void
do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
- unsigned int got_offset)
+ unsigned int got_offset, uint64_t addend)
{
+ Local_got_entry_key key(symndx, addend);
Local_got_offsets::const_iterator p =
- this->local_got_offsets_.find(symndx);
+ this->local_got_offsets_.find(key);
if (p != this->local_got_offsets_.end())
p->second->set_offset(got_type, got_offset);
else
{
Got_offset_list* g = new Got_offset_list(got_type, got_offset);
std::pair<Local_got_offsets::iterator, bool> ins =
- this->local_got_offsets_.insert(std::make_pair(symndx, g));
+ this->local_got_offsets_.insert(std::make_pair(key, g));
gold_assert(ins.second);
}
}
private:
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
- typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
+ typedef Unordered_map<Local_got_entry_key, Got_offset_list*,
+ Local_got_entry_key::hash,
+ Local_got_entry_key::equal_to> Local_got_offsets;
// GOT offsets for local non-TLS symbols, and tp-relative offsets
- // for TLS symbols, indexed by symbol number.
+ // for TLS symbols, indexed by local got entry key class.
Local_got_offsets local_got_offsets_;
// For each input section, the offset of the input section in its
// output section. This is INVALID_ADDRESS if the input section requires a
set_output_local_symbol_count(unsigned int value)
{ this->output_local_symbol_count_ = value; }
+ // Return the output view for a section.
+ unsigned char*
+ do_get_output_view(unsigned int, section_size_type*) const;
+
private:
// For convenience.
typedef Sized_relobj_file<size, big_endian> This;
unsigned int sh_type, unsigned int shndx,
const unsigned char* prelocs, size_t reloc_count,
unsigned char* view, section_size_type view_size,
- Reloc_symbol_changes** reloc_map);
+ Reloc_symbol_changes** reloc_map,
+ const Sized_target<size, big_endian>* target);
template<int sh_type>
void
unsigned int shndx, const unsigned char* prelocs,
size_t reloc_count, unsigned char* view,
section_size_type view_size,
- Reloc_symbol_changes** reloc_map);
+ Reloc_symbol_changes** reloc_map,
+ const Sized_target<size, big_endian>* target);
// Find all functions in a section.
void
std::vector<Deferred_layout> deferred_layout_;
// The list of relocation sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_relocs_;
+ // Pointer to the list of output views; valid only during do_relocate().
+ const Views* output_views_;
};
// A class to manage the list of all objects.
unsigned int reloc_shndx;
// Section header of relocation section.
const unsigned char* reloc_shdr;
+ // Info about how relocs should be handled
+ Relocatable_relocs* rr;
// Section index of section being relocated.
unsigned int data_shndx;
// Section header of data section.