old-cross-binutils/gold/target.h
Alan Modra 91a65d2fe8 [GOLD] Relocate::relocate() params
Some linker code editing needs to change multiple insns.  In some
cases multiple relocations are involved and it is not sufficient to
make the changes independently as relocations are processed, because
doing so might lead to a partial edit.  So in order to safely edit we
need all the relocations available in relocate().  Also, to emit
edited relocs corresponding to the edited code sequence we need some
way to pass information from relocate() to relocate_relocs(),
particularly if the edit depends on insns.  We can't modify input
relocs in relocate() as they are mmapped PROT_READ, nor it is
particularly clean to write relocs to the output at that stage.  So
add a Relocatable_relocs* field to relinfo to mark edited relocs.

Given that relocate is passed the raw reloc pointer, it makes sense to
remove the rel/rela parameter and r_type too.  However, that means the
mips relocate() needs to know whether SHT_REL or SHT_RELA relocs are
being processed.  So add a rel_type for mips, which also has the
benefit of removing relocate() overloading there.

This patch adds the infrastructure without making use of it.

Note that relinfo->rr will be NULL if not outputting relocations.

	* object.h (struct Relocate_info): Add "rr".
	* reloc.h (Relocatable_relocs::set_strategy): New accessor.
	* reloc.cc (Sized_relobj_file::do_relocate_sections): Init
	relinfo.rr for relocate_section and relocate_relocs.
	* powerpc.cc (relocate): Add rel_type and preloc parameters.
	Delete rela and r_type params, instead recalculate these from
	preloc.
	(relocate_relocs): Delete Relocatable_relocs* param, instead
	use relinfo->rr.
	* aarch64.cc: Likewise.
	* arm.cc: Likewise.
	* i386.cc: Likewise.
	* mips.cc: Likewise.
	* s390.cc: Likewise.
	* sparc.cc: Likewise.
	* target.h: Likewise.
	* tilegx.cc: Likewise.
	* x86_64.cc: Likewise.
	* testsuite/testfile.cc: Likewise.
	* target-reloc.h (relocate_section): Adjust to suit.
	(apply_relocation, relocate_relocs): Likewise.
2015-12-09 10:36:43 +10:30

1110 lines
38 KiB
C++

// target.h -- target support for gold -*- C++ -*-
// Copyright (C) 2006-2015 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
// MA 02110-1301, USA.
// The abstract class Target is the interface for target specific
// support. It defines abstract methods which each target must
// implement. Typically there will be one target per processor, but
// in some cases it may be necessary to have subclasses.
// For speed and consistency we want to use inline functions to handle
// relocation processing. So besides implementations of the abstract
// methods, each target is expected to define a template
// specialization of the relocation functions.
#ifndef GOLD_TARGET_H
#define GOLD_TARGET_H
#include "elfcpp.h"
#include "options.h"
#include "parameters.h"
#include "stringpool.h"
#include "debug.h"
namespace gold
{
class Object;
class Relobj;
template<int size, bool big_endian>
class Sized_relobj;
template<int size, bool big_endian>
class Sized_relobj_file;
class Relocatable_relocs;
template<int size, bool big_endian>
struct Relocate_info;
class Reloc_symbol_changes;
class Symbol;
template<int size>
class Sized_symbol;
class Symbol_table;
class Output_data;
class Output_data_got_base;
class Output_section;
class Input_objects;
class Task;
struct Symbol_location;
class Versions;
// The abstract class for target specific handling.
class Target
{
public:
virtual ~Target()
{ }
// Return the bit size that this target implements. This should
// return 32 or 64.
int
get_size() const
{ return this->pti_->size; }
// Return whether this target is big-endian.
bool
is_big_endian() const
{ return this->pti_->is_big_endian; }
// Machine code to store in e_machine field of ELF header.
elfcpp::EM
machine_code() const
{ return this->pti_->machine_code; }
// Processor specific flags to store in e_flags field of ELF header.
elfcpp::Elf_Word
processor_specific_flags() const
{ return this->processor_specific_flags_; }
// Whether processor specific flags are set at least once.
bool
are_processor_specific_flags_set() const
{ return this->are_processor_specific_flags_set_; }
// Whether this target has a specific make_symbol function.
bool
has_make_symbol() const
{ return this->pti_->has_make_symbol; }
// Whether this target has a specific resolve function.
bool
has_resolve() const
{ return this->pti_->has_resolve; }
// Whether this target has a specific code fill function.
bool
has_code_fill() const
{ return this->pti_->has_code_fill; }
// Return the default name of the dynamic linker.
const char*
dynamic_linker() const
{ return this->pti_->dynamic_linker; }
// Return the default address to use for the text segment.
uint64_t
default_text_segment_address() const
{ return this->pti_->default_text_segment_address; }
// Return the ABI specified page size.
uint64_t
abi_pagesize() const
{
if (parameters->options().max_page_size() > 0)
return parameters->options().max_page_size();
else
return this->pti_->abi_pagesize;
}
// Return the common page size used on actual systems.
uint64_t
common_pagesize() const
{
if (parameters->options().common_page_size() > 0)
return std::min(parameters->options().common_page_size(),
this->abi_pagesize());
else
return std::min(this->pti_->common_pagesize,
this->abi_pagesize());
}
// Return whether PF_X segments must contain nothing but the contents of
// SHF_EXECINSTR sections (no non-executable data, no headers).
bool
isolate_execinstr() const
{ return this->pti_->isolate_execinstr; }
uint64_t
rosegment_gap() const
{ return this->pti_->rosegment_gap; }
// If we see some object files with .note.GNU-stack sections, and
// some objects files without them, this returns whether we should
// consider the object files without them to imply that the stack
// should be executable.
bool
is_default_stack_executable() const
{ return this->pti_->is_default_stack_executable; }
// Return a character which may appear as a prefix for a wrap
// symbol. If this character appears, we strip it when checking for
// wrapping and add it back when forming the final symbol name.
// This should be '\0' if not special prefix is required, which is
// the normal case.
char
wrap_char() const
{ return this->pti_->wrap_char; }
// Return the special section index which indicates a small common
// symbol. This will return SHN_UNDEF if there are no small common
// symbols.
elfcpp::Elf_Half
small_common_shndx() const
{ return this->pti_->small_common_shndx; }
// Return values to add to the section flags for the section holding
// small common symbols.
elfcpp::Elf_Xword
small_common_section_flags() const
{
gold_assert(this->pti_->small_common_shndx != elfcpp::SHN_UNDEF);
return this->pti_->small_common_section_flags;
}
// Return the special section index which indicates a large common
// symbol. This will return SHN_UNDEF if there are no large common
// symbols.
elfcpp::Elf_Half
large_common_shndx() const
{ return this->pti_->large_common_shndx; }
// Return values to add to the section flags for the section holding
// large common symbols.
elfcpp::Elf_Xword
large_common_section_flags() const
{
gold_assert(this->pti_->large_common_shndx != elfcpp::SHN_UNDEF);
return this->pti_->large_common_section_flags;
}
// This hook is called when an output section is created.
void
new_output_section(Output_section* os) const
{ this->do_new_output_section(os); }
// This is called to tell the target to complete any sections it is
// handling. After this all sections must have their final size.
void
finalize_sections(Layout* layout, const Input_objects* input_objects,
Symbol_table* symtab)
{ return this->do_finalize_sections(layout, input_objects, symtab); }
// Return the value to use for a global symbol which needs a special
// value in the dynamic symbol table. This will only be called if
// the backend first calls symbol->set_needs_dynsym_value().
uint64_t
dynsym_value(const Symbol* sym) const
{ return this->do_dynsym_value(sym); }
// Return a string to use to fill out a code section. This is
// basically one or more NOPS which must fill out the specified
// length in bytes.
std::string
code_fill(section_size_type length) const
{ return this->do_code_fill(length); }
// Return whether SYM is known to be defined by the ABI. This is
// used to avoid inappropriate warnings about undefined symbols.
bool
is_defined_by_abi(const Symbol* sym) const
{ return this->do_is_defined_by_abi(sym); }
// Adjust the output file header before it is written out. VIEW
// points to the header in external form. LEN is the length.
void
adjust_elf_header(unsigned char* view, int len)
{ return this->do_adjust_elf_header(view, len); }
// Return address and size to plug into eh_frame FDEs associated with a PLT.
void
plt_fde_location(const Output_data* plt, unsigned char* oview,
uint64_t* address, off_t* len) const
{ return this->do_plt_fde_location(plt, oview, address, len); }
// Return whether NAME is a local label name. This is used to implement the
// --discard-locals options.
bool
is_local_label_name(const char* name) const
{ return this->do_is_local_label_name(name); }
// Get the symbol index to use for a target specific reloc.
unsigned int
reloc_symbol_index(void* arg, unsigned int type) const
{ return this->do_reloc_symbol_index(arg, type); }
// Get the addend to use for a target specific reloc.
uint64_t
reloc_addend(void* arg, unsigned int type, uint64_t addend) const
{ return this->do_reloc_addend(arg, type, addend); }
// Return the PLT address to use for a global symbol.
uint64_t
plt_address_for_global(const Symbol* sym) const
{ return this->do_plt_address_for_global(sym); }
// Return the PLT address to use for a local symbol.
uint64_t
plt_address_for_local(const Relobj* object, unsigned int symndx) const
{ return this->do_plt_address_for_local(object, symndx); }
// Return the offset to use for the GOT_INDX'th got entry which is
// for a local tls symbol specified by OBJECT, SYMNDX.
int64_t
tls_offset_for_local(const Relobj* object,
unsigned int symndx,
unsigned int got_indx) const
{ return do_tls_offset_for_local(object, symndx, got_indx); }
// Return the offset to use for the GOT_INDX'th got entry which is
// for global tls symbol GSYM.
int64_t
tls_offset_for_global(Symbol* gsym, unsigned int got_indx) const
{ return do_tls_offset_for_global(gsym, got_indx); }
// For targets that use function descriptors, if LOC is the location
// of a function, modify it to point at the function entry location.
void
function_location(Symbol_location* loc) const
{ return do_function_location(loc); }
// Return whether this target can use relocation types to determine
// if a function's address is taken.
bool
can_check_for_function_pointers() const
{ return this->do_can_check_for_function_pointers(); }
// Return whether a relocation to a merged section can be processed
// to retrieve the contents.
bool
can_icf_inline_merge_sections () const
{ return this->pti_->can_icf_inline_merge_sections; }
// Whether a section called SECTION_NAME may have function pointers to
// sections not eligible for safe ICF folding.
virtual bool
section_may_have_icf_unsafe_pointers(const char* section_name) const
{ return this->do_section_may_have_icf_unsafe_pointers(section_name); }
// Return the base to use for the PC value in an FDE when it is
// encoded using DW_EH_PE_datarel. This does not appear to be
// documented anywhere, but it is target specific. Any use of
// DW_EH_PE_datarel in gcc requires defining a special macro
// (ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX) to output the value.
uint64_t
ehframe_datarel_base() const
{ return this->do_ehframe_datarel_base(); }
// Return true if a reference to SYM from a reloc of type R_TYPE
// means that the current function may call an object compiled
// without -fsplit-stack. SYM is known to be defined in an object
// compiled without -fsplit-stack.
bool
is_call_to_non_split(const Symbol* sym, unsigned int r_type) const
{ return this->do_is_call_to_non_split(sym, r_type); }
// A function starts at OFFSET in section SHNDX in OBJECT. That
// function was compiled with -fsplit-stack, but it refers to a
// function which was compiled without -fsplit-stack. VIEW is a
// modifiable view of the section; VIEW_SIZE is the size of the
// view. The target has to adjust the function so that it allocates
// enough stack.
void
calls_non_split(Relobj* object, unsigned int shndx,
section_offset_type fnoffset, section_size_type fnsize,
unsigned char* view, section_size_type view_size,
std::string* from, std::string* to) const
{
this->do_calls_non_split(object, shndx, fnoffset, fnsize, view, view_size,
from, to);
}
// Make an ELF object.
template<int size, bool big_endian>
Object*
make_elf_object(const std::string& name, Input_file* input_file,
off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
{ return this->do_make_elf_object(name, input_file, offset, ehdr); }
// Make an output section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
{ return this->do_make_output_section(name, type, flags); }
// Return true if target wants to perform relaxation.
bool
may_relax() const
{
// Run the dummy relaxation pass twice if relaxation debugging is enabled.
if (is_debugging_enabled(DEBUG_RELAXATION))
return true;
return this->do_may_relax();
}
// Perform a relaxation pass. Return true if layout may be changed.
bool
relax(int pass, const Input_objects* input_objects, Symbol_table* symtab,
Layout* layout, const Task* task)
{
// Run the dummy relaxation pass twice if relaxation debugging is enabled.
if (is_debugging_enabled(DEBUG_RELAXATION))
return pass < 2;
return this->do_relax(pass, input_objects, symtab, layout, task);
}
// Return the target-specific name of attributes section. This is
// NULL if a target does not use attributes section or if it uses
// the default section name ".gnu.attributes".
const char*
attributes_section() const
{ return this->pti_->attributes_section; }
// Return the vendor name of vendor attributes.
const char*
attributes_vendor() const
{ return this->pti_->attributes_vendor; }
// Whether a section called NAME is an attribute section.
bool
is_attributes_section(const char* name) const
{
return ((this->pti_->attributes_section != NULL
&& strcmp(name, this->pti_->attributes_section) == 0)
|| strcmp(name, ".gnu.attributes") == 0);
}
// Return a bit mask of argument types for attribute with TAG.
int
attribute_arg_type(int tag) const
{ return this->do_attribute_arg_type(tag); }
// Return the attribute tag of the position NUM in the list of fixed
// attributes. Normally there is no reordering and
// attributes_order(NUM) == NUM.
int
attributes_order(int num) const
{ return this->do_attributes_order(num); }
// When a target is selected as the default target, we call this method,
// which may be used for expensive, target-specific initialization.
void
select_as_default_target()
{ this->do_select_as_default_target(); }
// Return the value to store in the EI_OSABI field in the ELF
// header.
elfcpp::ELFOSABI
osabi() const
{ return this->osabi_; }
// Set the value to store in the EI_OSABI field in the ELF header.
void
set_osabi(elfcpp::ELFOSABI osabi)
{ this->osabi_ = osabi; }
// Define target-specific standard symbols.
void
define_standard_symbols(Symbol_table* symtab, Layout* layout)
{ this->do_define_standard_symbols(symtab, layout); }
// Return the output section name to use given an input section
// name, or NULL if no target specific name mapping is required.
// Set *PLEN to the length of the name if returning non-NULL.
const char*
output_section_name(const Relobj* relobj,
const char* name,
size_t* plen) const
{ return this->do_output_section_name(relobj, name, plen); }
// Add any special sections for this symbol to the gc work list.
void
gc_mark_symbol(Symbol_table* symtab, Symbol* sym) const
{ this->do_gc_mark_symbol(symtab, sym); }
// Return the name of the entry point symbol.
const char*
entry_symbol_name() const
{ return this->pti_->entry_symbol_name; }
// Return the size in bits of SHT_HASH entry.
int
hash_entry_size() const
{ return this->pti_->hash_entry_size; }
// Whether the target has a custom set_dynsym_indexes method.
bool
has_custom_set_dynsym_indexes() const
{ return this->do_has_custom_set_dynsym_indexes(); }
// Custom set_dynsym_indexes method for a target.
unsigned int
set_dynsym_indexes(std::vector<Symbol*>* dyn_symbols, unsigned int index,
std::vector<Symbol*>* syms, Stringpool* dynpool,
Versions* versions, Symbol_table* symtab) const
{
return this->do_set_dynsym_indexes(dyn_symbols, index, syms, dynpool,
versions, symtab);
}
// Get the custom dynamic tag value.
unsigned int
dynamic_tag_custom_value(elfcpp::DT tag) const
{ return this->do_dynamic_tag_custom_value(tag); }
// Adjust the value written to the dynamic symbol table.
void
adjust_dyn_symbol(const Symbol* sym, unsigned char* view) const
{ this->do_adjust_dyn_symbol(sym, view); }
// Return whether to include the section in the link.
bool
should_include_section(elfcpp::Elf_Word sh_type) const
{ return this->do_should_include_section(sh_type); }
protected:
// This struct holds the constant information for a child class. We
// use a struct to avoid the overhead of virtual function calls for
// simple information.
struct Target_info
{
// Address size (32 or 64).
int size;
// Whether the target is big endian.
bool is_big_endian;
// The code to store in the e_machine field of the ELF header.
elfcpp::EM machine_code;
// Whether this target has a specific make_symbol function.
bool has_make_symbol;
// Whether this target has a specific resolve function.
bool has_resolve;
// Whether this target has a specific code fill function.
bool has_code_fill;
// Whether an object file with no .note.GNU-stack sections implies
// that the stack should be executable.
bool is_default_stack_executable;
// Whether a relocation to a merged section can be processed to
// retrieve the contents.
bool can_icf_inline_merge_sections;
// Prefix character to strip when checking for wrapping.
char wrap_char;
// The default dynamic linker name.
const char* dynamic_linker;
// The default text segment address.
uint64_t default_text_segment_address;
// The ABI specified page size.
uint64_t abi_pagesize;
// The common page size used by actual implementations.
uint64_t common_pagesize;
// Whether PF_X segments must contain nothing but the contents of
// SHF_EXECINSTR sections (no non-executable data, no headers).
bool isolate_execinstr;
// If nonzero, distance from the text segment to the read-only segment.
uint64_t rosegment_gap;
// The special section index for small common symbols; SHN_UNDEF
// if none.
elfcpp::Elf_Half small_common_shndx;
// The special section index for large common symbols; SHN_UNDEF
// if none.
elfcpp::Elf_Half large_common_shndx;
// Section flags for small common section.
elfcpp::Elf_Xword small_common_section_flags;
// Section flags for large common section.
elfcpp::Elf_Xword large_common_section_flags;
// Name of attributes section if it is not ".gnu.attributes".
const char* attributes_section;
// Vendor name of vendor attributes.
const char* attributes_vendor;
// Name of the main entry point to the program.
const char* entry_symbol_name;
// Size (in bits) of SHT_HASH entry. Always equal to 32, except for
// 64-bit S/390.
const int hash_entry_size;
};
Target(const Target_info* pti)
: pti_(pti), processor_specific_flags_(0),
are_processor_specific_flags_set_(false), osabi_(elfcpp::ELFOSABI_NONE)
{ }
// Virtual function which may be implemented by the child class.
virtual void
do_new_output_section(Output_section*) const
{ }
// Virtual function which may be implemented by the child class.
virtual void
do_finalize_sections(Layout*, const Input_objects*, Symbol_table*)
{ }
// Virtual function which may be implemented by the child class.
virtual uint64_t
do_dynsym_value(const Symbol*) const
{ gold_unreachable(); }
// Virtual function which must be implemented by the child class if
// needed.
virtual std::string
do_code_fill(section_size_type) const
{ gold_unreachable(); }
// Virtual function which may be implemented by the child class.
virtual bool
do_is_defined_by_abi(const Symbol*) const
{ return false; }
// Adjust the output file header before it is written out. VIEW
// points to the header in external form. LEN is the length, and
// will be one of the values of elfcpp::Elf_sizes<size>::ehdr_size.
// By default, we set the EI_OSABI field if requested (in
// Sized_target).
virtual void
do_adjust_elf_header(unsigned char*, int) = 0;
// Return address and size to plug into eh_frame FDEs associated with a PLT.
virtual void
do_plt_fde_location(const Output_data* plt, unsigned char* oview,
uint64_t* address, off_t* len) const;
// Virtual function which may be overridden by the child class.
virtual bool
do_is_local_label_name(const char*) const;
// Virtual function that must be overridden by a target which uses
// target specific relocations.
virtual unsigned int
do_reloc_symbol_index(void*, unsigned int) const
{ gold_unreachable(); }
// Virtual function that must be overridden by a target which uses
// target specific relocations.
virtual uint64_t
do_reloc_addend(void*, unsigned int, uint64_t) const
{ gold_unreachable(); }
// Virtual functions that must be overridden by a target that uses
// STT_GNU_IFUNC symbols.
virtual uint64_t
do_plt_address_for_global(const Symbol*) const
{ gold_unreachable(); }
virtual uint64_t
do_plt_address_for_local(const Relobj*, unsigned int) const
{ gold_unreachable(); }
virtual int64_t
do_tls_offset_for_local(const Relobj*, unsigned int, unsigned int) const
{ gold_unreachable(); }
virtual int64_t
do_tls_offset_for_global(Symbol*, unsigned int) const
{ gold_unreachable(); }
virtual void
do_function_location(Symbol_location*) const = 0;
// Virtual function which may be overriden by the child class.
virtual bool
do_can_check_for_function_pointers() const
{ return false; }
// Virtual function which may be overridden by the child class. We
// recognize some default sections for which we don't care whether
// they have function pointers.
virtual bool
do_section_may_have_icf_unsafe_pointers(const char* section_name) const
{
// We recognize sections for normal vtables, construction vtables and
// EH frames.
return (!is_prefix_of(".rodata._ZTV", section_name)
&& !is_prefix_of(".data.rel.ro._ZTV", section_name)
&& !is_prefix_of(".rodata._ZTC", section_name)
&& !is_prefix_of(".data.rel.ro._ZTC", section_name)
&& !is_prefix_of(".eh_frame", section_name));
}
virtual uint64_t
do_ehframe_datarel_base() const
{ gold_unreachable(); }
// Virtual function which may be overridden by the child class. The
// default implementation is that any function not defined by the
// ABI is a call to a non-split function.
virtual bool
do_is_call_to_non_split(const Symbol* sym, unsigned int) const;
// Virtual function which may be overridden by the child class.
virtual void
do_calls_non_split(Relobj* object, unsigned int, section_offset_type,
section_size_type, unsigned char*, section_size_type,
std::string*, std::string*) const;
// make_elf_object hooks. There are four versions of these for
// different address sizes and endianness.
// Set processor specific flags.
void
set_processor_specific_flags(elfcpp::Elf_Word flags)
{
this->processor_specific_flags_ = flags;
this->are_processor_specific_flags_set_ = true;
}
#ifdef HAVE_TARGET_32_LITTLE
// Virtual functions which may be overridden by the child class.
virtual Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<32, false>&);
#endif
#ifdef HAVE_TARGET_32_BIG
// Virtual functions which may be overridden by the child class.
virtual Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<32, true>&);
#endif
#ifdef HAVE_TARGET_64_LITTLE
// Virtual functions which may be overridden by the child class.
virtual Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<64, false>& ehdr);
#endif
#ifdef HAVE_TARGET_64_BIG
// Virtual functions which may be overridden by the child class.
virtual Object*
do_make_elf_object(const std::string& name, Input_file* input_file,
off_t offset, const elfcpp::Ehdr<64, true>& ehdr);
#endif
// Virtual functions which may be overridden by the child class.
virtual Output_section*
do_make_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags);
// Virtual function which may be overridden by the child class.
virtual bool
do_may_relax() const
{ return parameters->options().relax(); }
// Virtual function which may be overridden by the child class.
virtual bool
do_relax(int, const Input_objects*, Symbol_table*, Layout*, const Task*)
{ return false; }
// A function for targets to call. Return whether BYTES/LEN matches
// VIEW/VIEW_SIZE at OFFSET.
bool
match_view(const unsigned char* view, section_size_type view_size,
section_offset_type offset, const char* bytes, size_t len) const;
// Set the contents of a VIEW/VIEW_SIZE to nops starting at OFFSET
// for LEN bytes.
void
set_view_to_nop(unsigned char* view, section_size_type view_size,
section_offset_type offset, size_t len) const;
// This must be overridden by the child class if it has target-specific
// attributes subsection in the attribute section.
virtual int
do_attribute_arg_type(int) const
{ gold_unreachable(); }
// This may be overridden by the child class.
virtual int
do_attributes_order(int num) const
{ return num; }
// This may be overridden by the child class.
virtual void
do_select_as_default_target()
{ }
// This may be overridden by the child class.
virtual void
do_define_standard_symbols(Symbol_table*, Layout*)
{ }
// This may be overridden by the child class.
virtual const char*
do_output_section_name(const Relobj*, const char*, size_t*) const
{ return NULL; }
// This may be overridden by the child class.
virtual void
do_gc_mark_symbol(Symbol_table*, Symbol*) const
{ }
// This may be overridden by the child class.
virtual bool
do_has_custom_set_dynsym_indexes() const
{ return false; }
// This may be overridden by the child class.
virtual unsigned int
do_set_dynsym_indexes(std::vector<Symbol*>*, unsigned int,
std::vector<Symbol*>*, Stringpool*, Versions*,
Symbol_table*) const
{ gold_unreachable(); }
// This may be overridden by the child class.
virtual unsigned int
do_dynamic_tag_custom_value(elfcpp::DT) const
{ gold_unreachable(); }
// This may be overridden by the child class.
virtual void
do_adjust_dyn_symbol(const Symbol*, unsigned char*) const
{ }
// This may be overridden by the child class.
virtual bool
do_should_include_section(elfcpp::Elf_Word) const
{ return true; }
private:
// The implementations of the four do_make_elf_object virtual functions are
// almost identical except for their sizes and endianness. We use a template.
// for their implementations.
template<int size, bool big_endian>
inline Object*
do_make_elf_object_implementation(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<size, big_endian>&);
Target(const Target&);
Target& operator=(const Target&);
// The target information.
const Target_info* pti_;
// Processor-specific flags.
elfcpp::Elf_Word processor_specific_flags_;
// Whether the processor-specific flags are set at least once.
bool are_processor_specific_flags_set_;
// If not ELFOSABI_NONE, the value to put in the EI_OSABI field of
// the ELF header. This is handled at this level because it is
// OS-specific rather than processor-specific.
elfcpp::ELFOSABI osabi_;
};
// The abstract class for a specific size and endianness of target.
// Each actual target implementation class should derive from an
// instantiation of Sized_target.
template<int size, bool big_endian>
class Sized_target : public Target
{
public:
// Make a new symbol table entry for the target. This should be
// overridden by a target which needs additional information in the
// symbol table. This will only be called if has_make_symbol()
// returns true.
virtual Sized_symbol<size>*
make_symbol() const
{ gold_unreachable(); }
// Resolve a symbol for the target. This should be overridden by a
// target which needs to take special action. TO is the
// pre-existing symbol. SYM is the new symbol, seen in OBJECT.
// VERSION is the version of SYM. This will only be called if
// has_resolve() returns true.
virtual void
resolve(Symbol*, const elfcpp::Sym<size, big_endian>&, Object*,
const char*)
{ gold_unreachable(); }
// Process the relocs for a section, and record information of the
// mapping from source to destination sections. This mapping is later
// used to determine unreferenced garbage sections. This procedure is
// only called during garbage collection.
virtual void
gc_process_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_symbols) = 0;
// Scan the relocs for a section, and record any information
// required for the symbol. SYMTAB is the symbol table. OBJECT is
// the object in which the section appears. DATA_SHNDX is the
// section index that these relocs apply to. SH_TYPE is the type of
// the relocation section, SHT_REL or SHT_RELA. PRELOCS points to
// the relocation data. RELOC_COUNT is the number of relocs.
// LOCAL_SYMBOL_COUNT is the number of local symbols.
// OUTPUT_SECTION is the output section.
// NEEDS_SPECIAL_OFFSET_HANDLING is true if offsets to the output
// sections are not mapped as usual. PLOCAL_SYMBOLS points to the
// local symbol data from OBJECT. GLOBAL_SYMBOLS is the array of
// pointers to the global symbol table from OBJECT.
virtual void
scan_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_symbols) = 0;
// Relocate section data. SH_TYPE is the type of the relocation
// section, SHT_REL or SHT_RELA. PRELOCS points to the relocation
// information. RELOC_COUNT is the number of relocs.
// OUTPUT_SECTION is the output section.
// NEEDS_SPECIAL_OFFSET_HANDLING is true if offsets must be mapped
// to correspond to the output section. VIEW is a view into the
// output file holding the section contents, VIEW_ADDRESS is the
// virtual address of the view, and VIEW_SIZE is the size of the
// view. If NEEDS_SPECIAL_OFFSET_HANDLING is true, the VIEW_xx
// parameters refer to the complete output section data, not just
// the input section data.
virtual void
relocate_section(const Relocate_info<size, big_endian>*,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
const Reloc_symbol_changes*) = 0;
// Scan the relocs during a relocatable link. The parameters are
// like scan_relocs, with an additional Relocatable_relocs
// parameter, used to record the disposition of the relocs.
virtual void
scan_relocatable_relocs(Symbol_table* symtab,
Layout* layout,
Sized_relobj_file<size, big_endian>* object,
unsigned int data_shndx,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
bool needs_special_offset_handling,
size_t local_symbol_count,
const unsigned char* plocal_symbols,
Relocatable_relocs*) = 0;
// Emit relocations for a section during a relocatable link, and for
// --emit-relocs. The parameters are like relocate_section, with
// additional parameters for the view of the output reloc section.
virtual void
relocate_relocs(const Relocate_info<size, big_endian>*,
unsigned int sh_type,
const unsigned char* prelocs,
size_t reloc_count,
Output_section* output_section,
typename elfcpp::Elf_types<size>::Elf_Off
offset_in_output_section,
unsigned char* view,
typename elfcpp::Elf_types<size>::Elf_Addr view_address,
section_size_type view_size,
unsigned char* reloc_view,
section_size_type reloc_view_size) = 0;
// Perform target-specific processing in a relocatable link. This is
// only used if we use the relocation strategy RELOC_SPECIAL.
// RELINFO points to a Relocation_info structure. SH_TYPE is the relocation
// section type. PRELOC_IN points to the original relocation. RELNUM is
// the index number of the relocation in the relocation section.
// OUTPUT_SECTION is the output section to which the relocation is applied.
// OFFSET_IN_OUTPUT_SECTION is the offset of the relocation input section
// within the output section. VIEW points to the output view of the
// output section. VIEW_ADDRESS is output address of the view. VIEW_SIZE
// is the size of the output view and PRELOC_OUT points to the new
// relocation in the output object.
//
// A target only needs to override this if the generic code in
// target-reloc.h cannot handle some relocation types.
virtual void
relocate_special_relocatable(const Relocate_info<size, big_endian>*
/*relinfo */,
unsigned int /* sh_type */,
const unsigned char* /* preloc_in */,
size_t /* relnum */,
Output_section* /* output_section */,
typename elfcpp::Elf_types<size>::Elf_Off
/* offset_in_output_section */,
unsigned char* /* view */,
typename elfcpp::Elf_types<size>::Elf_Addr
/* view_address */,
section_size_type /* view_size */,
unsigned char* /* preloc_out*/)
{ gold_unreachable(); }
// Return the number of entries in the GOT. This is only used for
// laying out the incremental link info sections. A target needs
// to implement this to support incremental linking.
virtual unsigned int
got_entry_count() const
{ gold_unreachable(); }
// Return the number of entries in the PLT. This is only used for
// laying out the incremental link info sections. A target needs
// to implement this to support incremental linking.
virtual unsigned int
plt_entry_count() const
{ gold_unreachable(); }
// Return the offset of the first non-reserved PLT entry. This is
// only used for laying out the incremental link info sections.
// A target needs to implement this to support incremental linking.
virtual unsigned int
first_plt_entry_offset() const
{ gold_unreachable(); }
// Return the size of each PLT entry. This is only used for
// laying out the incremental link info sections. A target needs
// to implement this to support incremental linking.
virtual unsigned int
plt_entry_size() const
{ gold_unreachable(); }
// Return the size of each GOT entry. This is only used for
// laying out the incremental link info sections. A target needs
// to implement this if its GOT size is different.
virtual unsigned int
got_entry_size() const
{ return size / 8; }
// Create the GOT and PLT sections for an incremental update.
// A target needs to implement this to support incremental linking.
virtual Output_data_got_base*
init_got_plt_for_update(Symbol_table*,
Layout*,
unsigned int /* got_count */,
unsigned int /* plt_count */)
{ gold_unreachable(); }
// Reserve a GOT entry for a local symbol, and regenerate any
// necessary dynamic relocations.
virtual void
reserve_local_got_entry(unsigned int /* got_index */,
Sized_relobj<size, big_endian>* /* obj */,
unsigned int /* r_sym */,
unsigned int /* got_type */)
{ gold_unreachable(); }
// Reserve a GOT entry for a global symbol, and regenerate any
// necessary dynamic relocations.
virtual void
reserve_global_got_entry(unsigned int /* got_index */, Symbol* /* gsym */,
unsigned int /* got_type */)
{ gold_unreachable(); }
// Register an existing PLT entry for a global symbol.
// A target needs to implement this to support incremental linking.
virtual void
register_global_plt_entry(Symbol_table*, Layout*,
unsigned int /* plt_index */,
Symbol*)
{ gold_unreachable(); }
// Force a COPY relocation for a given symbol.
// A target needs to implement this to support incremental linking.
virtual void
emit_copy_reloc(Symbol_table*, Symbol*, Output_section*, off_t)
{ gold_unreachable(); }
// Apply an incremental relocation.
virtual void
apply_relocation(const Relocate_info<size, big_endian>* /* relinfo */,
typename elfcpp::Elf_types<size>::Elf_Addr /* r_offset */,
unsigned int /* r_type */,
typename elfcpp::Elf_types<size>::Elf_Swxword /* r_addend */,
const Symbol* /* gsym */,
unsigned char* /* view */,
typename elfcpp::Elf_types<size>::Elf_Addr /* address */,
section_size_type /* view_size */)
{ gold_unreachable(); }
// Handle target specific gc actions when adding a gc reference from
// SRC_OBJ, SRC_SHNDX to a location specified by DST_OBJ, DST_SHNDX
// and DST_OFF.
void
gc_add_reference(Symbol_table* symtab,
Relobj* src_obj,
unsigned int src_shndx,
Relobj* dst_obj,
unsigned int dst_shndx,
typename elfcpp::Elf_types<size>::Elf_Addr dst_off) const
{
this->do_gc_add_reference(symtab, src_obj, src_shndx,
dst_obj, dst_shndx, dst_off);
}
protected:
Sized_target(const Target::Target_info* pti)
: Target(pti)
{
gold_assert(pti->size == size);
gold_assert(pti->is_big_endian ? big_endian : !big_endian);
}
// Set the EI_OSABI field if requested.
virtual void
do_adjust_elf_header(unsigned char*, int);
// Handle target specific gc actions when adding a gc reference.
virtual void
do_gc_add_reference(Symbol_table*, Relobj*, unsigned int,
Relobj*, unsigned int,
typename elfcpp::Elf_types<size>::Elf_Addr) const
{ }
virtual void
do_function_location(Symbol_location*) const
{ }
};
} // End namespace gold.
#endif // !defined(GOLD_TARGET_H)