Line 1... |
Line 1... |
// target.h -- target support for gold -*- C++ -*-
|
// target.h -- target support for gold -*- C++ -*-
|
|
|
// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
// Written by Ian Lance Taylor <iant@google.com>.
|
|
|
// This file is part of gold.
|
// This file is part of gold.
|
|
|
// This program is free software; you can redistribute it and/or modify
|
// This program is free software; you can redistribute it and/or modify
|
Line 68... |
Line 68... |
{
|
{
|
public:
|
public:
|
virtual ~Target()
|
virtual ~Target()
|
{ }
|
{ }
|
|
|
// Virtual function which is set to return true by a target if
|
|
// it can use relocation types to determine if a function's
|
|
// pointer is taken.
|
|
virtual bool
|
|
can_check_for_function_pointers() const
|
|
{ return false; }
|
|
|
|
// This function is used in ICF (icf.cc). This is set to true by
|
|
// the target if a relocation to a merged section can be processed
|
|
// to retrieve the contents of the merged section.
|
|
virtual bool
|
|
can_icf_inline_merge_sections () const
|
|
{ return false; }
|
|
|
|
// 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
|
|
{
|
|
// 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));
|
|
}
|
|
|
|
// Return the bit size that this target implements. This should
|
// Return the bit size that this target implements. This should
|
// return 32 or 64.
|
// return 32 or 64.
|
int
|
int
|
get_size() const
|
get_size() const
|
{ return this->pti_->size; }
|
{ return this->pti_->size; }
|
Line 272... |
Line 244... |
// Get the addend to use for a target specific reloc.
|
// Get the addend to use for a target specific reloc.
|
uint64_t
|
uint64_t
|
reloc_addend(void* arg, unsigned int type, uint64_t addend) const
|
reloc_addend(void* arg, unsigned int type, uint64_t addend) const
|
{ return this->do_reloc_addend(arg, type, addend); }
|
{ return this->do_reloc_addend(arg, type, addend); }
|
|
|
// Return the PLT section to use for a global symbol. This is used
|
// Return the PLT address to use for a global symbol. This is used
|
// for STT_GNU_IFUNC symbols.
|
// for STT_GNU_IFUNC symbols. The symbol's plt_offset is relative
|
Output_data*
|
// to this PLT address.
|
plt_section_for_global(const Symbol* sym) const
|
uint64_t
|
{ return this->do_plt_section_for_global(sym); }
|
plt_address_for_global(const Symbol* sym) const
|
|
{ return this->do_plt_address_for_global(sym); }
|
// Return the PLT section to use for a local symbol. This is used
|
|
// for STT_GNU_IFUNC symbols.
|
// Return the PLT address to use for a local symbol. This is used
|
Output_data*
|
// for STT_GNU_IFUNC symbols. The symbol's plt_offset is relative
|
plt_section_for_local(const Relobj* object, unsigned int symndx) const
|
// to this PLT address.
|
{ return this->do_plt_section_for_local(object, symndx); }
|
uint64_t
|
|
plt_address_for_local(const Relobj* object, unsigned int symndx) const
|
|
{ return this->do_plt_address_for_local(object, symndx); }
|
|
|
|
// 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
|
// Return true if a reference to SYM from a reloc of type R_TYPE
|
// means that the current function may call an object compiled
|
// means that the current function may call an object compiled
|
// without -fsplit-stack. SYM is known to be defined in an object
|
// without -fsplit-stack. SYM is known to be defined in an object
|
// compiled without -fsplit-stack.
|
// compiled without -fsplit-stack.
|
Line 383... |
Line 384... |
// which may be used for expensive, target-specific initialization.
|
// which may be used for expensive, target-specific initialization.
|
void
|
void
|
select_as_default_target()
|
select_as_default_target()
|
{ this->do_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; }
|
|
|
protected:
|
protected:
|
// This struct holds the constant information for a child class. We
|
// This struct holds the constant information for a child class. We
|
// use a struct to avoid the overhead of virtual function calls for
|
// use a struct to avoid the overhead of virtual function calls for
|
// simple information.
|
// simple information.
|
struct Target_info
|
struct Target_info
|
Line 404... |
Line 416... |
// Whether this target has a specific code fill function.
|
// Whether this target has a specific code fill function.
|
bool has_code_fill;
|
bool has_code_fill;
|
// Whether an object file with no .note.GNU-stack sections implies
|
// Whether an object file with no .note.GNU-stack sections implies
|
// that the stack should be executable.
|
// that the stack should be executable.
|
bool is_default_stack_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.
|
// Prefix character to strip when checking for wrapping.
|
char wrap_char;
|
char wrap_char;
|
// The default dynamic linker name.
|
// The default dynamic linker name.
|
const char* dynamic_linker;
|
const char* dynamic_linker;
|
// The default text segment address.
|
// The default text segment address.
|
Line 432... |
Line 447... |
const char* attributes_vendor;
|
const char* attributes_vendor;
|
};
|
};
|
|
|
Target(const Target_info* pti)
|
Target(const Target_info* pti)
|
: pti_(pti), processor_specific_flags_(0),
|
: pti_(pti), processor_specific_flags_(0),
|
are_processor_specific_flags_set_(false)
|
are_processor_specific_flags_set_(false), osabi_(elfcpp::ELFOSABI_NONE)
|
{ }
|
{ }
|
|
|
// Virtual function which may be implemented by the child class.
|
// Virtual function which may be implemented by the child class.
|
virtual void
|
virtual void
|
do_new_output_section(Output_section*) const
|
do_new_output_section(Output_section*) const
|
Line 464... |
Line 479... |
{ return false; }
|
{ return false; }
|
|
|
// Adjust the output file header before it is written out. VIEW
|
// Adjust the output file header before it is written out. VIEW
|
// points to the header in external form. LEN is the length, and
|
// 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.
|
// will be one of the values of elfcpp::Elf_sizes<size>::ehdr_size.
|
// By default, we do nothing.
|
// By default, we set the EI_OSABI field if requested (in
|
|
// Sized_target).
|
virtual void
|
virtual void
|
do_adjust_elf_header(unsigned char*, int) const
|
do_adjust_elf_header(unsigned char*, int) const = 0;
|
{ }
|
|
|
|
// Virtual function which may be overridden by the child class.
|
// Virtual function which may be overridden by the child class.
|
virtual bool
|
virtual bool
|
do_is_local_label_name(const char*) const;
|
do_is_local_label_name(const char*) const;
|
|
|
Line 487... |
Line 502... |
do_reloc_addend(void*, unsigned int, uint64_t) const
|
do_reloc_addend(void*, unsigned int, uint64_t) const
|
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
|
|
// Virtual functions that must be overridden by a target that uses
|
// Virtual functions that must be overridden by a target that uses
|
// STT_GNU_IFUNC symbols.
|
// STT_GNU_IFUNC symbols.
|
virtual Output_data*
|
virtual uint64_t
|
do_plt_section_for_global(const Symbol*) const
|
do_plt_address_for_global(const Symbol*) const
|
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
|
|
virtual Output_data*
|
virtual uint64_t
|
do_plt_section_for_local(const Relobj*, unsigned int) const
|
do_plt_address_for_local(const Relobj*, unsigned int) const
|
|
{ gold_unreachable(); }
|
|
|
|
// 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(); }
|
{ gold_unreachable(); }
|
|
|
// Virtual function which may be overridden by the child class. The
|
// Virtual function which may be overridden by the child class. The
|
// default implementation is that any function not defined by the
|
// default implementation is that any function not defined by the
|
// ABI is a call to a non-split function.
|
// ABI is a call to a non-split function.
|
Line 607... |
Line 646... |
const Target_info* pti_;
|
const Target_info* pti_;
|
// Processor-specific flags.
|
// Processor-specific flags.
|
elfcpp::Elf_Word processor_specific_flags_;
|
elfcpp::Elf_Word processor_specific_flags_;
|
// Whether the processor-specific flags are set at least once.
|
// Whether the processor-specific flags are set at least once.
|
bool are_processor_specific_flags_set_;
|
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.
|
// The abstract class for a specific size and endianness of target.
|
// Each actual target implementation class should derive from an
|
// Each actual target implementation class should derive from an
|
// instantiation of Sized_target.
|
// instantiation of Sized_target.
|
Line 827... |
Line 870... |
|
|
// Register an existing PLT entry for a global symbol.
|
// Register an existing PLT entry for a global symbol.
|
// A target needs to implement this to support incremental linking.
|
// A target needs to implement this to support incremental linking.
|
|
|
virtual void
|
virtual void
|
register_global_plt_entry(unsigned int /* plt_index */,
|
register_global_plt_entry(Symbol_table*, Layout*,
|
|
unsigned int /* plt_index */,
|
Symbol*)
|
Symbol*)
|
{ gold_unreachable(); }
|
{ gold_unreachable(); }
|
|
|
// Force a COPY relocation for a given symbol.
|
// Force a COPY relocation for a given symbol.
|
// A target needs to implement this to support incremental linking.
|
// A target needs to implement this to support incremental linking.
|
Line 858... |
Line 902... |
: Target(pti)
|
: Target(pti)
|
{
|
{
|
gold_assert(pti->size == size);
|
gold_assert(pti->size == size);
|
gold_assert(pti->is_big_endian ? big_endian : !big_endian);
|
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) const;
|
};
|
};
|
|
|
} // End namespace gold.
|
} // End namespace gold.
|
|
|
#endif // !defined(GOLD_TARGET_H)
|
#endif // !defined(GOLD_TARGET_H)
|