// object.h -- support for an object file for linking in gold -*- C++ -*-
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
Output_section* output_section;
// Whether this section has special handling for offsets.
bool needs_special_offset_handling;
+ // Whether the data section is allocated (has the SHF_ALLOC flag set).
+ bool is_data_section_allocated;
};
// Relocations in an object file. This is read in read_relocs and
release()
{ this->input_file_->file().release(); }
+ // Return whether we should just read symbols from this file.
+ bool
+ just_symbols() const
+ { return this->input_file()->just_symbols(); }
+
// Return the sized target structure associated with this object.
// This is like the target method but it returns a pointer of
// appropriate checked type.
template<int size, bool big_endian>
Sized_target<size, big_endian>*
- sized_target(ACCEPT_SIZE_ENDIAN_ONLY) const;
+ sized_target() const;
// Get the number of sections.
unsigned int
section_flags(unsigned int shndx)
{ return this->do_section_flags(shndx); }
+ // Return the section address given a section index.
+ uint64_t
+ section_address(unsigned int shndx)
+ { return this->do_section_address(shndx); }
+
// Return the section type given a section index.
unsigned int
section_type(unsigned int shndx)
virtual uint64_t
do_section_flags(unsigned int shndx) = 0;
+ // Get section address--implemented by child class.
+ virtual uint64_t
+ do_section_address(unsigned int shndx) = 0;
+
// Get section type--implemented by child class.
virtual unsigned int
do_section_type(unsigned int shndx) = 0;
template<int size, bool big_endian>
inline Sized_target<size, big_endian>*
-Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY) const
+Object::sized_target() const
{
gold_assert(this->target_->get_size() == size);
gold_assert(this->target_->is_big_endian() ? big_endian : !big_endian);
void
set_needs_output_dynsym_entry()
{
+ gold_assert(!this->is_section_symbol());
this->output_dynsym_index_ = 0;
}
unsigned int
output_dynsym_index() const
{
- gold_assert(this->output_dynsym_index_ != 0);
+ gold_assert(this->output_dynsym_index_ != 0
+ && this->output_dynsym_index_ != -1U);
return this->output_dynsym_index_;
}
// Record that this is a section symbol.
void
set_is_section_symbol()
- { this->is_section_symbol_ = true; }
+ {
+ gold_assert(!this->needs_output_dynsym_entry());
+ this->is_section_symbol_ = true;
+ }
// Record that this is a TLS symbol.
void
} u_;
};
+// A GOT offset list. A symbol may have more than one GOT offset
+// (e.g., when mixing modules compiled with two different TLS models),
+// but will usually have at most one. GOT_TYPE identifies the type of
+// GOT entry; its values are specific to each target.
+
+class Got_offset_list
+{
+ public:
+ Got_offset_list()
+ : got_type_(-1U), got_offset_(0), got_next_(NULL)
+ { }
+
+ Got_offset_list(unsigned int got_type, unsigned int got_offset)
+ : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
+ { }
+
+ ~Got_offset_list()
+ {
+ if (this->got_next_ != NULL)
+ {
+ delete this->got_next_;
+ this->got_next_ = NULL;
+ }
+ }
+
+ // Initialize the fields to their default values.
+ void
+ init()
+ {
+ this->got_type_ = -1U;
+ this->got_offset_ = 0;
+ this->got_next_ = NULL;
+ }
+
+ // Set the offset for the GOT entry of type GOT_TYPE.
+ void
+ set_offset(unsigned int got_type, unsigned int got_offset)
+ {
+ if (this->got_type_ == -1U)
+ {
+ this->got_type_ = got_type;
+ this->got_offset_ = got_offset;
+ }
+ else
+ {
+ for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
+ {
+ if (g->got_type_ == got_type)
+ {
+ g->got_offset_ = got_offset;
+ return;
+ }
+ }
+ Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+ g->got_next_ = this->got_next_;
+ this->got_next_ = g;
+ }
+ }
+
+ // Return the offset for a GOT entry of type GOT_TYPE.
+ unsigned int
+ get_offset(unsigned int got_type) const
+ {
+ for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+ {
+ if (g->got_type_ == got_type)
+ return g->got_offset_;
+ }
+ return -1U;
+ }
+
+ private:
+ unsigned int got_type_;
+ unsigned int got_offset_;
+ Got_offset_list* got_next_;
+};
+
// A regular object file. This is size and endian specific.
template<int size, bool big_endian>
// Return the appropriate Sized_target structure.
Sized_target<size, big_endian>*
sized_target()
- {
- return this->Object::sized_target
- SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
- SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
- }
-
- // Return the value of the local symbol symndx.
- Address
- local_symbol_value(unsigned int symndx) const;
+ { return this->Object::sized_target<size, big_endian>(); }
+ // Record that local symbol SYM needs a dynamic symbol entry.
void
set_needs_output_dynsym_entry(unsigned int sym)
{
// Return whether the local symbol SYMNDX has a GOT offset.
// For TLS symbols, the GOT entry will hold its tp-relative offset.
bool
- local_has_got_offset(unsigned int symndx) const
+ local_has_got_offset(unsigned int symndx, unsigned int got_type) const
{
- return (this->local_got_offsets_.find(symndx)
- != this->local_got_offsets_.end());
+ 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 the local symbol SYMNDX.
unsigned int
- local_got_offset(unsigned int symndx) const
+ local_got_offset(unsigned int symndx, unsigned int got_type) const
{
Local_got_offsets::const_iterator p =
this->local_got_offsets_.find(symndx);
gold_assert(p != this->local_got_offsets_.end());
- return p->second;
+ unsigned int off = p->second->get_offset(got_type);
+ gold_assert(off != -1U);
+ return off;
}
// Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
void
- set_local_got_offset(unsigned int symndx, unsigned int got_offset)
- {
- std::pair<Local_got_offsets::iterator, bool> ins =
- this->local_got_offsets_.insert(std::make_pair(symndx, got_offset));
- gold_assert(ins.second);
- }
-
- // Return whether the local TLS symbol SYMNDX has a GOT offset.
- // The GOT entry at this offset will contain a module index. If
- // NEED_PAIR is true, a second entry immediately following the first
- // will contain the dtv-relative offset.
- bool
- local_has_tls_got_offset(unsigned int symndx, bool need_pair) const
- {
- typename Local_tls_got_offsets::const_iterator p =
- this->local_tls_got_offsets_.find(symndx);
- if (p == this->local_tls_got_offsets_.end()
- || (need_pair && !p->second.have_pair_))
- return false;
- return true;
- }
-
- // Return the offset of the GOT entry for the local TLS symbol SYMNDX.
- // If NEED_PAIR is true, we need the offset of a pair of GOT entries;
- // otherwise we need the offset of the GOT entry for the module index.
- unsigned int
- local_tls_got_offset(unsigned int symndx, bool need_pair) const
- {
- typename Local_tls_got_offsets::const_iterator p =
- this->local_tls_got_offsets_.find(symndx);
- gold_assert(p != this->local_tls_got_offsets_.end());
- gold_assert(!need_pair || p->second.have_pair_);
- return p->second.got_offset_;
- }
-
- // Set the offset of the GOT entry for the local TLS symbol SYMNDX
- // to GOT_OFFSET. If HAVE_PAIR is true, we have a pair of GOT entries;
- // otherwise, we have just a single entry for the module index.
- void
- set_local_tls_got_offset(unsigned int symndx, unsigned int got_offset,
- bool have_pair)
+ set_local_got_offset(unsigned int symndx, unsigned int got_type,
+ unsigned int got_offset)
{
- typename Local_tls_got_offsets::iterator p =
- this->local_tls_got_offsets_.find(symndx);
- if (p != this->local_tls_got_offsets_.end())
- {
- // An entry already existed for this symbol. This can happen
- // if we see a relocation asking for the module index before
- // a relocation asking for the pair. In that case, the original
- // GOT entry will remain, but won't get used by any further
- // relocations.
- p->second.got_offset_ = got_offset;
- gold_assert(have_pair);
- p->second.have_pair_ = true;
- }
+ Local_got_offsets::const_iterator p =
+ this->local_got_offsets_.find(symndx);
+ if (p != this->local_got_offsets_.end())
+ p->second->set_offset(got_type, got_offset);
else
{
- std::pair<typename Local_tls_got_offsets::iterator, bool> ins =
- this->local_tls_got_offsets_.insert(
- std::make_pair(symndx, Tls_got_entry(got_offset, have_pair)));
+ 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));
gold_assert(ins.second);
}
}
do_section_flags(unsigned int shndx)
{ return this->elf_file_.section_flags(shndx); }
+ // Return section address.
+ uint64_t
+ do_section_address(unsigned int shndx)
+ { return this->elf_file_.section_addr(shndx); }
+
// Return section type.
unsigned int
do_section_type(unsigned int shndx)
relocate_sections(const General_options& options, const Symbol_table*,
const Layout*, const unsigned char* pshdrs, Views*);
+ // Scan the input relocations for --emit-relocs.
+ void
+ emit_relocs_scan(const General_options&, Symbol_table*, Layout*,
+ const unsigned char* plocal_syms,
+ const Read_relocs_data::Relocs_list::iterator&);
+
+ // Scan the input relocations for --emit-relocs, templatized on the
+ // type of the relocation section.
+ template<int sh_type>
+ void
+ emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*,
+ const unsigned char* plocal_syms,
+ const Read_relocs_data::Relocs_list::iterator&,
+ Relocatable_relocs*);
+
+ // Emit the relocs for --emit-relocs.
+ void
+ emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
+ unsigned int sh_type, const unsigned char* prelocs,
+ size_t reloc_count, Output_section*, off_t output_offset,
+ unsigned char* view, Address address,
+ section_size_type view_size,
+ unsigned char* reloc_view, section_size_type reloc_view_size);
+
+ // Emit the relocs for --emit-relocs, templatized on the type of the
+ // relocation section.
+ template<int sh_type>
+ void
+ emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
+ const unsigned char* prelocs, size_t reloc_count,
+ Output_section*, off_t output_offset,
+ unsigned char* view, Address address,
+ section_size_type view_size,
+ unsigned char* reloc_view,
+ section_size_type reloc_view_size);
+
// Initialize input to output maps for section symbols in merged
// sections.
void
{
this->local_values_.clear();
this->local_got_offsets_.clear();
- this->local_tls_got_offsets_.clear();
}
// The GOT offsets of local symbols. This map also stores GOT offsets
// for tp-relative offsets for TLS symbols.
- typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets;
+ typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
// The TLS GOT offsets of local symbols. The map stores the offsets
// for either a single GOT entry that holds the module index of a TLS
// GOT offsets for local non-TLS symbols, and tp-relative offsets
// for TLS symbols, indexed by symbol number.
Local_got_offsets local_got_offsets_;
- // GOT offsets for local TLS symbols, indexed by symbol number
- // and GOT entry type.
- Local_tls_got_offsets local_tls_got_offsets_;
// Whether this object has a GNU style .eh_frame section.
bool has_eh_frame_;
};
{
public:
Input_objects()
- : relobj_list_(), dynobj_list_(), target_(NULL), sonames_(),
- system_library_directory_()
+ : relobj_list_(), dynobj_list_(), sonames_(), system_library_directory_()
{ }
// The type of the list of input relocateable objects.
bool
add_object(Object*);
- // Get the target we should use for the output file.
- Target*
- target() const
- { return this->target_; }
-
// For each dynamic object, check whether we've seen all of its
// explicit dependencies.
void
Relobj_list relobj_list_;
// The list of dynamic objects included in the link.
Dynobj_list dynobj_list_;
- // The target.
- Target* target_;
// SONAMEs that we have seen.
Unordered_set<std::string> sonames_;
// The directory in which we find the libc.so.