2009-10-30 Doug Kwan <dougkwan@google.com>

elfcpp/ChangeLog:
	* arm.h (EF_ARM_BE8, EF_ARM_EABIMASK, EF_ARM_EABI_UNKNOWN,
	EF_ARM_EABI_VER1, EF_ARM_EABI_VER2, EF_ARM_EABI_VER3,
	EF_ARM_EABI_VER4, EF_ARM_EABI_VER5): New enums for processor-specific
	flags.
	(arm_eabi_version): New inline function.
	* elfcpp.h: Add a comment about DT_ENCODING.

gold/ChangeLog:
	* arm.cc (Arm_relobj::processor_specific_flags): New method
	definition.
	(Arm_relobj::do_read_symbols): New method declaration.
	(Arm_relobj::processor_specific_flags_): New data member declaration.
	(Arm_dynobj): New class definition.
	(Target_arm::do_finalize_sections): Add input_objects parameter.
	(Target_arm::do_adjust_elf_header): New method declaration.
	(Target_arm::are_eabi_versions_compatible,
	(Target_arm::merge_processor_specific_flags): New method declaration.
	(Target_arm::do_make_elf_object): New overloaded method definitions
	and declaration.
	(Arm_relobj::do_read_symbols): New method definition.
	(Arm_dynobj::do_read_symbols): Ditto.
	(Target_arm::do_finalize_sections): Add input_objects parameters.
	Merge processor-specific flags from all input objects.
	(Target_arm::are_eabi_versions_compatible,
	Target_arm::merge_processor_specific_flags,
	Target_arm::do_adjust_elf_header, Target_arm::do_make_elf_object):
	New method definitions.
	* i386.cc (Target_i386::do_finalize_sections): Add unnamed
	Input_objects pointer type parameter.
	* layout.cc (Layout::finalize): Pass input objects to target's.
	finalize_sections function.
	* output.cc (Output_file_header::do_sized_write): Set ELF file
	header's processor-specific flags.
	* powerpc.cc (Target_powerpc::do_finalize_sections): Add unnamed
	Input_objects pointer type parameter.
	* sparc.cc (Target_sparc::do_finalize_sections): Same.
	* target.h (Input_objects): New forward class declaration.
	(Target::processor_specific_flags,
	Target::are_processor_specific_flags_sect): New method definitions.
	(Target::finalize_sections): Add input_objects parameter.
	(Target::Target): Initialize processor_specific_flags_ and
	are_processor_specific_flags_set_.
	(Target::do_finalize_sections): Add unnamed Input_objects pointer type
	parameter.
	(Target::set_processor_specific_flags): New method definition.
	(Target::processor_specific_flags_,
	Target::are_processor_specific_flags_set_): New data member
	declarations.
	* x86_64.cc (Target_x86_64::do_finalize_sections): Add unnamed
	Input_objects pointer type parameter.
This commit is contained in:
Doug Kwan 2009-10-30 18:49:59 +00:00
parent ebabffbd89
commit d5b40221bc
12 changed files with 391 additions and 19 deletions

View File

@ -1,3 +1,12 @@
2009-10-30 Doug Kwan <dougkwan@google.com>
* arm.h (EF_ARM_BE8, EF_ARM_EABIMASK, EF_ARM_EABI_UNKNOWN,
EF_ARM_EABI_VER1, EF_ARM_EABI_VER2, EF_ARM_EABI_VER3,
EF_ARM_EABI_VER4, EF_ARM_EABI_VER5): New enums for processor-specific
flags.
(arm_eabi_version): New inline function.
* elfcpp.h: Add a comment about DT_ENCODING.
2009-10-16 Doug Kwan <dougkwan@google.com>
* elfcpp/elfcpp.h (DT_PREINIT_ARRAY): Correct enum value.

View File

@ -199,6 +199,29 @@ enum
// 160 - 255 Unallocated
};
// e_flags values used for ARM. We only support flags defined in AAELF.
enum
{
EF_ARM_BE8 = 0x00800000,
// Mask to extract EABI version, not really a flag value.
EF_ARM_EABIMASK = 0xFF000000,
EF_ARM_EABI_UNKNOWN = 0x00000000,
EF_ARM_EABI_VER1 = 0x01000000,
EF_ARM_EABI_VER2 = 0x02000000,
EF_ARM_EABI_VER3 = 0x03000000,
EF_ARM_EABI_VER4 = 0x04000000,
EF_ARM_EABI_VER5 = 0x05000000,
};
// Extract EABI version from flags.
inline Elf_Word
arm_eabi_version(Elf_Word flags)
{ return flags & EF_ARM_EABIMASK; }
} // End namespace elfcpp.
#endif // !defined(ELFCPP_ARM_H)

View File

@ -656,7 +656,11 @@ enum DT
DT_FINI_ARRAYSZ = 28,
DT_RUNPATH = 29,
DT_FLAGS = 30,
// This is used to mark a range of dynamic tags. It is not really
// a tag value.
DT_ENCODING = 32,
DT_PREINIT_ARRAY = 32,
DT_PREINIT_ARRAYSZ = 33,
DT_LOOS = 0x6000000d,

View File

@ -1,3 +1,48 @@
2009-10-30 Doug Kwan <dougkwan@google.com>
* arm.cc (Arm_relobj::processor_specific_flags): New method
definition.
(Arm_relobj::do_read_symbols): New method declaration.
(Arm_relobj::processor_specific_flags_): New data member declaration.
(Arm_dynobj): New class definition.
(Target_arm::do_finalize_sections): Add input_objects parameter.
(Target_arm::do_adjust_elf_header): New method declaration.
(Target_arm::are_eabi_versions_compatible,
(Target_arm::merge_processor_specific_flags): New method declaration.
(Target_arm::do_make_elf_object): New overloaded method definitions
and declaration.
(Arm_relobj::do_read_symbols): New method definition.
(Arm_dynobj::do_read_symbols): Ditto.
(Target_arm::do_finalize_sections): Add input_objects parameters.
Merge processor-specific flags from all input objects.
(Target_arm::are_eabi_versions_compatible,
Target_arm::merge_processor_specific_flags,
Target_arm::do_adjust_elf_header, Target_arm::do_make_elf_object):
New method definitions.
* i386.cc (Target_i386::do_finalize_sections): Add unnamed
Input_objects pointer type parameter.
* layout.cc (Layout::finalize): Pass input objects to target's.
finalize_sections function.
* output.cc (Output_file_header::do_sized_write): Set ELF file
header's processor-specific flags.
* powerpc.cc (Target_powerpc::do_finalize_sections): Add unnamed
Input_objects pointer type parameter.
* sparc.cc (Target_sparc::do_finalize_sections): Same.
* target.h (Input_objects): New forward class declaration.
(Target::processor_specific_flags,
Target::are_processor_specific_flags_sect): New method definitions.
(Target::finalize_sections): Add input_objects parameter.
(Target::Target): Initialize processor_specific_flags_ and
are_processor_specific_flags_set_.
(Target::do_finalize_sections): Add unnamed Input_objects pointer type
parameter.
(Target::set_processor_specific_flags): New method definition.
(Target::processor_specific_flags_,
Target::are_processor_specific_flags_set_): New data member
declarations.
* x86_64.cc (Target_x86_64::do_finalize_sections): Add unnamed
Input_objects pointer type parameter.
2009-10-30 Doug Kwan <dougkwan@google.com>
* arm.cc: Use Arm_address instead of elfcpp::Elf_types<32>::Elf_Addr.

View File

@ -947,6 +947,12 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
as_arm_relobj(Relobj* relobj)
{ return static_cast<Arm_relobj<big_endian>*>(relobj); }
// Processor-specific flags in ELF file header. This is valid only after
// reading symbols.
elfcpp::Elf_Word
processor_specific_flags() const
{ return this->processor_specific_flags_; }
protected:
// Post constructor setup.
void
@ -971,6 +977,10 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
const unsigned char* pshdrs,
typename Sized_relobj<32, big_endian>::Views* pivews);
// Read the symbol information.
void
do_read_symbols(Read_symbols_data* sd);
private:
// List of stub tables.
typedef std::vector<Stub_table<big_endian>*> Stub_table_list;
@ -978,6 +988,45 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
// Bit vector to tell if a local symbol is a thumb function or not.
// This is only valid after do_count_local_symbol is called.
std::vector<bool> local_symbol_is_thumb_function_;
// processor-specific flags in ELF file header.
elfcpp::Elf_Word processor_specific_flags_;
};
// Arm_dynobj class.
template<bool big_endian>
class Arm_dynobj : public Sized_dynobj<32, big_endian>
{
public:
Arm_dynobj(const std::string& name, Input_file* input_file, off_t offset,
const elfcpp::Ehdr<32, big_endian>& ehdr)
: Sized_dynobj<32, big_endian>(name, input_file, offset, ehdr),
processor_specific_flags_(0)
{ }
~Arm_dynobj()
{ }
// Downcast a base pointer to an Arm_relobj pointer. This is
// not type-safe but we only use Arm_relobj not the base class.
static Arm_dynobj<big_endian>*
as_arm_dynobj(Dynobj* dynobj)
{ return static_cast<Arm_dynobj<big_endian>*>(dynobj); }
// Processor-specific flags in ELF file header. This is valid only after
// reading symbols.
elfcpp::Elf_Word
processor_specific_flags() const
{ return this->processor_specific_flags_; }
protected:
// Read the symbol information.
void
do_read_symbols(Read_symbols_data* sd);
private:
// processor-specific flags in ELF file header.
elfcpp::Elf_Word processor_specific_flags_;
};
// Utilities for manipulating integers of up to 32-bits
@ -1120,7 +1169,7 @@ class Target_arm : public Sized_target<32, big_endian>
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(Layout*, const Input_objects*);
// Return the value to use for a dynamic symbol which requires special
// treatment.
@ -1196,6 +1245,10 @@ class Target_arm : public Sized_target<32, big_endian>
return static_cast<const Target_arm<big_endian>&>(parameters->target());
}
protected:
void
do_adjust_elf_header(unsigned char* view, int len) const;
private:
// The class which scans relocations.
class Scan
@ -1366,6 +1419,34 @@ class Target_arm : public Sized_target<32, big_endian>
this->rel_dyn_section(layout));
}
// Whether two EABI versions are compatible.
static bool
are_eabi_versions_compatible(elfcpp::Elf_Word v1, elfcpp::Elf_Word v2);
// Merge processor-specific flags from input object and those in the ELF
// header of the output.
void
merge_processor_specific_flags(const std::string&, elfcpp::Elf_Word);
Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<32, big_endian>& ehdr);
Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<32, !big_endian>&)
{ gold_unreachable(); }
Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<64, false>&)
{ gold_unreachable(); }
Object*
do_make_elf_object(const std::string&, Input_file*, off_t,
const elfcpp::Ehdr<64, true>&)
{ gold_unreachable(); }
// Information about this specific target which we pass to the
// general Target structure.
static const Target::Target_info arm_info;
@ -3250,6 +3331,42 @@ Arm_relobj<big_endian>::do_relocate_sections(
}
}
// Read the symbol information.
template<bool big_endian>
void
Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
{
// Call parent class to read symbol information.
Sized_relobj<32, big_endian>::do_read_symbols(sd);
// Read processor-specific flags in ELF file header.
const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset,
elfcpp::Elf_sizes<32>::ehdr_size,
true, false);
elfcpp::Ehdr<32, big_endian> ehdr(pehdr);
this->processor_specific_flags_ = ehdr.get_e_flags();
}
// Arm_dynobj methods.
// Read the symbol information.
template<bool big_endian>
void
Arm_dynobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
{
// Call parent class to read symbol information.
Sized_dynobj<32, big_endian>::do_read_symbols(sd);
// Read processor-specific flags in ELF file header.
const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset,
elfcpp::Elf_sizes<32>::ehdr_size,
true, false);
elfcpp::Ehdr<32, big_endian> ehdr(pehdr);
this->processor_specific_flags_ = ehdr.get_e_flags();
}
// A class to handle the PLT data.
template<bool big_endian>
@ -3950,8 +4067,33 @@ Target_arm<big_endian>::scan_relocs(Symbol_table* symtab,
template<bool big_endian>
void
Target_arm<big_endian>::do_finalize_sections(Layout* layout)
Target_arm<big_endian>::do_finalize_sections(
Layout* layout,
const Input_objects* input_objects)
{
// Merge processor-specific flags.
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
++p)
{
Arm_relobj<big_endian>* arm_relobj =
Arm_relobj<big_endian>::as_arm_relobj(*p);
this->merge_processor_specific_flags(
arm_relobj->name(),
arm_relobj->processor_specific_flags());
}
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
p != input_objects->dynobj_end();
++p)
{
Arm_dynobj<big_endian>* arm_dynobj =
Arm_dynobj<big_endian>::as_arm_dynobj(*p);
this->merge_processor_specific_flags(
arm_dynobj->name(),
arm_dynobj->processor_specific_flags());
}
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();
if (odyn != NULL)
@ -4588,6 +4730,130 @@ Target_arm<big_endian>::get_real_reloc_type (unsigned int r_type)
}
}
// Whether if two EABI versions V1 and V2 are compatible.
template<bool big_endian>
bool
Target_arm<big_endian>::are_eabi_versions_compatible(
elfcpp::Elf_Word v1,
elfcpp::Elf_Word v2)
{
// v4 and v5 are the same spec before and after it was released,
// so allow mixing them.
if ((v1 == elfcpp::EF_ARM_EABI_VER4 && v2 == elfcpp::EF_ARM_EABI_VER5)
|| (v1 == elfcpp::EF_ARM_EABI_VER5 && v2 == elfcpp::EF_ARM_EABI_VER4))
return true;
return v1 == v2;
}
// Combine FLAGS from an input object called NAME and the processor-specific
// flags in the ELF header of the output. Much of this is adapted from the
// processor-specific flags merging code in elf32_arm_merge_private_bfd_data
// in bfd/elf32-arm.c.
template<bool big_endian>
void
Target_arm<big_endian>::merge_processor_specific_flags(
const std::string& name,
elfcpp::Elf_Word flags)
{
if (this->are_processor_specific_flags_set())
{
elfcpp::Elf_Word out_flags = this->processor_specific_flags();
// Nothing to merge if flags equal to those in output.
if (flags == out_flags)
return;
// Complain about various flag mismatches.
elfcpp::Elf_Word version1 = elfcpp::arm_eabi_version(flags);
elfcpp::Elf_Word version2 = elfcpp::arm_eabi_version(out_flags);
if (!this->are_eabi_versions_compatible(version1, version2))
gold_error(_("Source object %s has EABI version %d but output has "
"EABI version %d."),
name.c_str(),
(flags & elfcpp::EF_ARM_EABIMASK) >> 24,
(out_flags & elfcpp::EF_ARM_EABIMASK) >> 24);
}
else
{
// If the input is the default architecture and had the default
// flags then do not bother setting the flags for the output
// architecture, instead allow future merges to do this. If no
// future merges ever set these flags then they will retain their
// uninitialised values, which surprise surprise, correspond
// to the default values.
if (flags == 0)
return;
// This is the first time, just copy the flags.
// We only copy the EABI version for now.
this->set_processor_specific_flags(flags & elfcpp::EF_ARM_EABIMASK);
}
}
// Adjust ELF file header.
template<bool big_endian>
void
Target_arm<big_endian>::do_adjust_elf_header(
unsigned char* view,
int len) const
{
gold_assert(len == elfcpp::Elf_sizes<32>::ehdr_size);
elfcpp::Ehdr<32, big_endian> ehdr(view);
unsigned char e_ident[elfcpp::EI_NIDENT];
memcpy(e_ident, ehdr.get_e_ident(), elfcpp::EI_NIDENT);
if (elfcpp::arm_eabi_version(this->processor_specific_flags())
== elfcpp::EF_ARM_EABI_UNKNOWN)
e_ident[elfcpp::EI_OSABI] = elfcpp::ELFOSABI_ARM;
else
e_ident[elfcpp::EI_OSABI] = 0;
e_ident[elfcpp::EI_ABIVERSION] = 0;
// FIXME: Do EF_ARM_BE8 adjustment.
elfcpp::Ehdr_write<32, big_endian> oehdr(view);
oehdr.put_e_ident(e_ident);
}
// do_make_elf_object to override the same function in the base class.
// We need to use a target-specific sub-class of Sized_relobj<32, big_endian>
// to store ARM specific information. Hence we need to have our own
// ELF object creation.
template<bool big_endian>
Object*
Target_arm<big_endian>::do_make_elf_object(
const std::string& name,
Input_file* input_file,
off_t offset, const elfcpp::Ehdr<32, big_endian>& ehdr)
{
int et = ehdr.get_e_type();
if (et == elfcpp::ET_REL)
{
Arm_relobj<big_endian>* obj =
new Arm_relobj<big_endian>(name, input_file, offset, ehdr);
obj->setup();
return obj;
}
else if (et == elfcpp::ET_DYN)
{
Sized_dynobj<32, big_endian>* obj =
new Arm_dynobj<big_endian>(name, input_file, offset, ehdr);
obj->setup();
return obj;
}
else
{
gold_error(_("%s: unsupported ELF file type %d"),
name.c_str(), et);
return NULL;
}
}
// The selector for arm object files.
template<bool big_endian>

View File

@ -95,7 +95,7 @@ class Target_i386 : public Target_freebsd<32, false>
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(Layout*, const Input_objects*);
// Return the value to use for a dynamic which requires special
// treatment.
@ -1552,7 +1552,7 @@ Target_i386::scan_relocs(Symbol_table* symtab,
// Finalize the sections.
void
Target_i386::do_finalize_sections(Layout* layout)
Target_i386::do_finalize_sections(Layout* layout, const Input_objects*)
{
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();

View File

@ -1509,7 +1509,7 @@ off_t
Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab,
Target* target, const Task* task)
{
target->finalize_sections(this);
target->finalize_sections(this, input_objects);
this->count_local_symbols(task, input_objects);

View File

@ -459,10 +459,7 @@ Output_file_header::do_sized_write(Output_file* of)
oehdr.put_e_phoff(this->segment_header_->offset());
oehdr.put_e_shoff(this->section_header_->offset());
// FIXME: The target needs to set the flags.
oehdr.put_e_flags(0);
oehdr.put_e_flags(this->target_->processor_specific_flags());
oehdr.put_e_ehsize(elfcpp::Elf_sizes<size>::ehdr_size);
if (this->segment_header_ == NULL)

View File

@ -92,7 +92,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols);
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(Layout*, const Input_objects*);
// Return the value to use for a dynamic which requires special
// treatment.
@ -1530,7 +1530,9 @@ Target_powerpc<size, big_endian>::scan_relocs(
template<int size, bool big_endian>
void
Target_powerpc<size, big_endian>::do_finalize_sections(Layout* layout)
Target_powerpc<size, big_endian>::do_finalize_sections(
Layout* layout,
const Input_objects*)
{
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();

View File

@ -94,7 +94,7 @@ class Target_sparc : public Sized_target<size, big_endian>
const unsigned char* plocal_symbols);
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(Layout*, const Input_objects*);
// Return the value to use for a dynamic which requires special
// treatment.
@ -2317,7 +2317,9 @@ Target_sparc<size, big_endian>::scan_relocs(
template<int size, bool big_endian>
void
Target_sparc<size, big_endian>::do_finalize_sections(Layout* layout)
Target_sparc<size, big_endian>::do_finalize_sections(
Layout* layout,
const Input_objects*)
{
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();

View File

@ -54,6 +54,7 @@ template<int size>
class Sized_symbol;
class Symbol_table;
class Output_section;
class Input_objects;
// The abstract class for target specific handling.
@ -79,6 +80,16 @@ class Target
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
@ -183,8 +194,8 @@ class Target
// 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)
{ return this->do_finalize_sections(layout); }
finalize_sections(Layout* layout, const Input_objects* input_objects)
{ return this->do_finalize_sections(layout, input_objects); }
// 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
@ -314,7 +325,8 @@ class Target
};
Target(const Target_info* pti)
: pti_(pti)
: pti_(pti), processor_specific_flags_(0),
are_processor_specific_flags_set_(false)
{ }
// Virtual function which may be implemented by the child class.
@ -324,7 +336,7 @@ class Target
// Virtual function which may be implemented by the child class.
virtual void
do_finalize_sections(Layout*)
do_finalize_sections(Layout*, const Input_objects*)
{ }
// Virtual function which may be implemented by the child class.
@ -364,6 +376,14 @@ class Target
// make_elf_object hooks. There are four versions of these for
// different address sizes and endianities.
// 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 overriden by the child class.
virtual Object*
@ -433,6 +453,10 @@ class 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_;
};
// The abstract class for a specific size and endianness of target.

View File

@ -102,7 +102,7 @@ class Target_x86_64 : public Target_freebsd<64, false>
// Finalize the sections.
void
do_finalize_sections(Layout*);
do_finalize_sections(Layout*, const Input_objects*);
// Return the value to use for a dynamic which requires special
// treatment.
@ -1642,7 +1642,7 @@ Target_x86_64::scan_relocs(Symbol_table* symtab,
// Finalize the sections.
void
Target_x86_64::do_finalize_sections(Layout* layout)
Target_x86_64::do_finalize_sections(Layout* layout, const Input_objects*)
{
// Fill in some more dynamic tags.
Output_data_dynamic* const odyn = layout->dynamic_data();