2010-04-07 Doug Kwan <dougkwan@google.com>

* arm.cc: Replace "endianity" with "endianness" in comments.
	(Arm_exidx_cantunwind): Ditto.
	(Arm_relobj::Arm_relobj): Initialize merge_flags_and_attribures.
	(Arm_relobj::merge_flags_and_attributes): New method.
	(Arm_relobj::merge_flags_and_attributes_): New data member.
	(Arm_exidx_cantunwind::do_fixed_endian_write): Fix formatting.
	(Arm_relobj::scan_sections_for_stubs): Ditto.
	(Arm_relobj::do_read_symbols): Check to see if we really want to
	merge processor-specific flags and attributes.  Exit early if
	an object is empty except for section names and the undefined symbol.
	(Target_arm::do_finalize_sections): Move check for ELF format to
	Arm_relobj::do_read_symbols.  Merge processor specific flags and
	attributes from a regular object only when we have determined that
	it is aapropriate.  Do not create an .ARM.attributes section in
	output if there is no regular input object.
	(Target_arm::merge_processor_specific_flags): Check
	--warn-mismatch before printing any error.
	(Target_arm::merge_object_attributes): Ditto.
	* gold.cc (queue_middle_tasks): Handle the case in which there is
	no regular object in input.
	* options.cc (General_options::parse_EB): New method.
	(General_options::parse_EL): Same.
	(General_options::General_options): Initialize endianness_.
	* options.h (-EB, -EL, -no-pipeline-knowledge, -p, --warn-mismatch):
	New options.
	(General_options::Endianness): New enum.
	(General_options::endianness): New method.
	(General_options::endianness_): New data member.
	* parameters.cc (Parameters::set_options): Check target endianness.
	(Parameters::set_target_once): Ditto.
	(Parameters::check_target_endianness): New method.
	(parameters_force_valid_target): If either -EL or -EB is specified,
	use it to define endianness of default target.
	* parameters.h (Parameters::check_target_endianness): New method
	declaration.
	* target.h (class Target): Change "endianity" to "endianness"
	in comments.
This commit is contained in:
Doug Kwan
2010-04-07 21:42:22 +00:00
parent 45ecb02a77
commit 7296d93387
8 changed files with 233 additions and 51 deletions

View File

@ -1,3 +1,43 @@
2010-04-07 Doug Kwan <dougkwan@google.com>
* arm.cc: Replace "endianity" with "endianness" in comments.
(Arm_exidx_cantunwind): Ditto.
(Arm_relobj::Arm_relobj): Initialize merge_flags_and_attribures.
(Arm_relobj::merge_flags_and_attributes): New method.
(Arm_relobj::merge_flags_and_attributes_): New data member.
(Arm_exidx_cantunwind::do_fixed_endian_write): Fix formatting.
(Arm_relobj::scan_sections_for_stubs): Ditto.
(Arm_relobj::do_read_symbols): Check to see if we really want to
merge processor-specific flags and attributes. Exit early if
an object is empty except for section names and the undefined symbol.
(Target_arm::do_finalize_sections): Move check for ELF format to
Arm_relobj::do_read_symbols. Merge processor specific flags and
attributes from a regular object only when we have determined that
it is aapropriate. Do not create an .ARM.attributes section in
output if there is no regular input object.
(Target_arm::merge_processor_specific_flags): Check
--warn-mismatch before printing any error.
(Target_arm::merge_object_attributes): Ditto.
* gold.cc (queue_middle_tasks): Handle the case in which there is
no regular object in input.
* options.cc (General_options::parse_EB): New method.
(General_options::parse_EL): Same.
(General_options::General_options): Initialize endianness_.
* options.h (-EB, -EL, -no-pipeline-knowledge, -p, --warn-mismatch):
New options.
(General_options::Endianness): New enum.
(General_options::endianness): New method.
(General_options::endianness_): New data member.
* parameters.cc (Parameters::set_options): Check target endianness.
(Parameters::set_target_once): Ditto.
(Parameters::check_target_endianness): New method.
(parameters_force_valid_target): If either -EL or -EB is specified,
use it to define endianness of default target.
* parameters.h (Parameters::check_target_endianness): New method
declaration.
* target.h (class Target): Change "endianity" to "endianness"
in comments.
2010-04-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de> 2010-04-07 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* configure.ac (AM_INIT_AUTOMAKE): Add option no-dist. * configure.ac (AM_INIT_AUTOMAKE): Add option no-dist.

View File

@ -602,7 +602,7 @@ class Reloc_stub : public Stub
// Otherwise, this points a relobj. We used the unsized and target // Otherwise, this points a relobj. We used the unsized and target
// independent Symbol and Relobj classes instead of Sized_symbol<32> and // independent Symbol and Relobj classes instead of Sized_symbol<32> and
// Arm_relobj. This is done to avoid making the stub class a template // Arm_relobj. This is done to avoid making the stub class a template
// as most of the stub machinery is endianity-neutral. However, it // as most of the stub machinery is endianness-neutral. However, it
// may require a bit of casting done by users of this class. // may require a bit of casting done by users of this class.
union union
{ {
@ -1065,7 +1065,7 @@ class Arm_exidx_cantunwind : public Output_section_data
} }
private: private:
// Implement do_write for a given endianity. // Implement do_write for a given endianness.
template<bool big_endian> template<bool big_endian>
void inline void inline
do_fixed_endian_write(Output_file*); do_fixed_endian_write(Output_file*);
@ -1426,7 +1426,8 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
stub_tables_(), local_symbol_is_thumb_function_(), stub_tables_(), local_symbol_is_thumb_function_(),
attributes_section_data_(NULL), mapping_symbols_info_(), attributes_section_data_(NULL), mapping_symbols_info_(),
section_has_cortex_a8_workaround_(NULL), exidx_section_map_(), section_has_cortex_a8_workaround_(NULL), exidx_section_map_(),
output_local_symbol_count_needs_update_(false) output_local_symbol_count_needs_update_(false),
merge_flags_and_attributes_(true)
{ } { }
~Arm_relobj() ~Arm_relobj()
@ -1565,6 +1566,11 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
void void
update_output_local_symbol_count(); update_output_local_symbol_count();
// Whether we want to merge processor-specific flags and attributes.
bool
merge_flags_and_attributes() const
{ return this->merge_flags_and_attributes_; }
protected: protected:
// Post constructor setup. // Post constructor setup.
void void
@ -1665,6 +1671,9 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
Exidx_section_map exidx_section_map_; Exidx_section_map exidx_section_map_;
// Whether output local symbol count needs updating. // Whether output local symbol count needs updating.
bool output_local_symbol_count_needs_update_; bool output_local_symbol_count_needs_update_;
// Whether we merge processor flags and attributes of this object to
// output.
bool merge_flags_and_attributes_;
}; };
// Arm_dynobj class. // Arm_dynobj class.
@ -4124,7 +4133,7 @@ Stub_template::Stub_template(
// Stub methods. // Stub methods.
// Template to implement do_write for a specific target endianity. // Template to implement do_write for a specific target endianness.
template<bool big_endian> template<bool big_endian>
void inline void inline
@ -4969,7 +4978,7 @@ Arm_input_section<big_endian>::do_reset_address_and_file_offset()
// Arm_exidx_cantunwind methods. // Arm_exidx_cantunwind methods.
// Write this to Output file OF for a fixed endianity. // Write this to Output file OF for a fixed endianness.
template<bool big_endian> template<bool big_endian>
void void
@ -4990,7 +4999,7 @@ Arm_exidx_cantunwind::do_fixed_endian_write(Output_file* of)
Arm_address output_offset = Arm_address output_offset =
arm_relobj->get_output_section_offset(this->shndx_); arm_relobj->get_output_section_offset(this->shndx_);
Arm_address section_start; Arm_address section_start;
if(output_offset != Arm_relobj<big_endian>::invalid_address) if (output_offset != Arm_relobj<big_endian>::invalid_address)
section_start = os->address() + output_offset; section_start = os->address() + output_offset;
else else
{ {
@ -5946,7 +5955,7 @@ Arm_relobj<big_endian>::scan_sections_for_stubs(
unsigned int index = this->adjust_shndx(shdr.get_sh_info()); unsigned int index = this->adjust_shndx(shdr.get_sh_info());
Arm_address output_offset = this->get_output_section_offset(index); Arm_address output_offset = this->get_output_section_offset(index);
Arm_address output_address; Arm_address output_address;
if(output_offset != invalid_address) if (output_offset != invalid_address)
output_address = out_sections[index]->address() + output_offset; output_address = out_sections[index]->address() + output_offset;
else else
{ {
@ -6327,6 +6336,16 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
// Call parent class to read symbol information. // Call parent class to read symbol information.
Sized_relobj<32, big_endian>::do_read_symbols(sd); Sized_relobj<32, big_endian>::do_read_symbols(sd);
// If this input file is a binary file, it has no processor
// specific flags and attributes section.
Input_file::Format format = this->input_file()->format();
if (format != Input_file::FORMAT_ELF)
{
gold_assert(format == Input_file::FORMAT_BINARY);
this->merge_flags_and_attributes_ = false;
return;
}
// Read processor-specific flags in ELF file header. // Read processor-specific flags in ELF file header.
const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset, const unsigned char* pehdr = this->get_view(elfcpp::file_header_offset,
elfcpp::Elf_sizes<32>::ehdr_size, elfcpp::Elf_sizes<32>::ehdr_size,
@ -6340,9 +6359,27 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size; const size_t shdr_size = elfcpp::Elf_sizes<32>::shdr_size;
const unsigned char* pshdrs = sd->section_headers->data(); const unsigned char* pshdrs = sd->section_headers->data();
const unsigned char *ps = pshdrs + shdr_size; const unsigned char *ps = pshdrs + shdr_size;
bool must_merge_flags_and_attributes = false;
for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size) for (unsigned int i = 1; i < this->shnum(); ++i, ps += shdr_size)
{ {
elfcpp::Shdr<32, big_endian> shdr(ps); elfcpp::Shdr<32, big_endian> shdr(ps);
// Sometimes an object has no contents except the section name string
// table and an empty symbol table with the undefined symbol. We
// don't want to merge processor-specific flags from such an object.
if (shdr.get_sh_type() == elfcpp::SHT_SYMTAB)
{
// Symbol table is not empty.
const elfcpp::Elf_types<32>::Elf_WXword sym_size =
elfcpp::Elf_sizes<32>::sym_size;
if (shdr.get_sh_size() > sym_size)
must_merge_flags_and_attributes = true;
}
else if (shdr.get_sh_type() != elfcpp::SHT_STRTAB)
// If this is neither an empty symbol table nor a string table,
// be conservative.
must_merge_flags_and_attributes = true;
if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES) if (shdr.get_sh_type() == elfcpp::SHT_ARM_ATTRIBUTES)
{ {
gold_assert(this->attributes_section_data_ == NULL); gold_assert(this->attributes_section_data_ == NULL);
@ -6367,6 +6404,13 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
} }
} }
// This is rare.
if (!must_merge_flags_and_attributes)
{
this->merge_flags_and_attributes_ = false;
return;
}
// Some tools are broken and they do not set the link of EXIDX sections. // Some tools are broken and they do not set the link of EXIDX sections.
// We look at the first relocation to figure out the linked sections. // We look at the first relocation to figure out the linked sections.
if (!deferred_exidx_sections.empty()) if (!deferred_exidx_sections.empty())
@ -7941,23 +7985,16 @@ Target_arm<big_endian>::do_finalize_sections(
p != input_objects->relobj_end(); p != input_objects->relobj_end();
++p) ++p)
{ {
// If this input file is a binary file, it has no processor
// specific flags and attributes section.
Input_file::Format format = (*p)->input_file()->format();
if (format != Input_file::FORMAT_ELF)
{
gold_assert(format == Input_file::FORMAT_BINARY);
continue;
}
Arm_relobj<big_endian>* arm_relobj = Arm_relobj<big_endian>* arm_relobj =
Arm_relobj<big_endian>::as_arm_relobj(*p); Arm_relobj<big_endian>::as_arm_relobj(*p);
this->merge_processor_specific_flags( if (arm_relobj->merge_flags_and_attributes())
arm_relobj->name(), {
arm_relobj->processor_specific_flags()); this->merge_processor_specific_flags(
this->merge_object_attributes(arm_relobj->name().c_str(), arm_relobj->name(),
arm_relobj->attributes_section_data()); arm_relobj->processor_specific_flags());
this->merge_object_attributes(arm_relobj->name().c_str(),
arm_relobj->attributes_section_data());
}
} }
for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin();
@ -8046,13 +8083,17 @@ Target_arm<big_endian>::do_finalize_sections(
} }
} }
// Create an .ARM.attributes section if there is not one already. // Create an .ARM.attributes section unless we have no regular input
Output_attributes_section_data* attributes_section = // object. In that case the output will be empty.
new Output_attributes_section_data(*this->attributes_section_data_); if (input_objects->number_of_relobjs() != 0)
layout->add_output_section_data(".ARM.attributes", {
elfcpp::SHT_ARM_ATTRIBUTES, 0, Output_attributes_section_data* attributes_section =
attributes_section, false, false, false, new Output_attributes_section_data(*this->attributes_section_data_);
false); layout->add_output_section_data(".ARM.attributes",
elfcpp::SHT_ARM_ATTRIBUTES, 0,
attributes_section, false, false, false,
false);
}
} }
// Return whether a direct absolute static relocation needs to be applied. // Return whether a direct absolute static relocation needs to be applied.
@ -8970,7 +9011,8 @@ Target_arm<big_endian>::merge_processor_specific_flags(
// Complain about various flag mismatches. // Complain about various flag mismatches.
elfcpp::Elf_Word version1 = elfcpp::arm_eabi_version(flags); elfcpp::Elf_Word version1 = elfcpp::arm_eabi_version(flags);
elfcpp::Elf_Word version2 = elfcpp::arm_eabi_version(out_flags); elfcpp::Elf_Word version2 = elfcpp::arm_eabi_version(out_flags);
if (!this->are_eabi_versions_compatible(version1, version2)) if (!this->are_eabi_versions_compatible(version1, version2)
&& parameters->options().warn_mismatch())
gold_error(_("Source object %s has EABI version %d but output has " gold_error(_("Source object %s has EABI version %d but output has "
"EABI version %d."), "EABI version %d."),
name.c_str(), name.c_str(),
@ -9381,7 +9423,8 @@ Target_arm<big_endian>::merge_object_attributes(
if (out_attr[elfcpp::Tag_ABI_FP_number_model].int_value() == 0) if (out_attr[elfcpp::Tag_ABI_FP_number_model].int_value() == 0)
out_attr[elfcpp::Tag_ABI_VFP_args].set_int_value( out_attr[elfcpp::Tag_ABI_VFP_args].set_int_value(
in_attr[elfcpp::Tag_ABI_VFP_args].int_value()); in_attr[elfcpp::Tag_ABI_VFP_args].int_value());
else if (in_attr[elfcpp::Tag_ABI_FP_number_model].int_value() != 0) else if (in_attr[elfcpp::Tag_ABI_FP_number_model].int_value() != 0
&& parameters->options().warn_mismatch())
gold_error(_("%s uses VFP register arguments, output does not"), gold_error(_("%s uses VFP register arguments, output does not"),
name); name);
} }
@ -9525,7 +9568,7 @@ Target_arm<big_endian>::merge_object_attributes(
&& (out_attr[i].int_value() == 'A' && (out_attr[i].int_value() == 'A'
|| out_attr[i].int_value() == 'R'))) || out_attr[i].int_value() == 'R')))
; // Do nothing. ; // Do nothing.
else else if (parameters->options().warn_mismatch())
{ {
gold_error gold_error
(_("conflicting architecture profiles %c/%c"), (_("conflicting architecture profiles %c/%c"),
@ -9580,7 +9623,9 @@ Target_arm<big_endian>::merge_object_attributes(
case elfcpp::Tag_PCS_config: case elfcpp::Tag_PCS_config:
if (out_attr[i].int_value() == 0) if (out_attr[i].int_value() == 0)
out_attr[i].set_int_value(in_attr[i].int_value()); out_attr[i].set_int_value(in_attr[i].int_value());
else if (in_attr[i].int_value() != 0 && out_attr[i].int_value() != 0) else if (in_attr[i].int_value() != 0
&& out_attr[i].int_value() != 0
&& parameters->options().warn_mismatch())
{ {
// It's sometimes ok to mix different configs, so this is only // It's sometimes ok to mix different configs, so this is only
// a warning. // a warning.
@ -9590,7 +9635,8 @@ Target_arm<big_endian>::merge_object_attributes(
case elfcpp::Tag_ABI_PCS_R9_use: case elfcpp::Tag_ABI_PCS_R9_use:
if (in_attr[i].int_value() != out_attr[i].int_value() if (in_attr[i].int_value() != out_attr[i].int_value()
&& out_attr[i].int_value() != elfcpp::AEABI_R9_unused && out_attr[i].int_value() != elfcpp::AEABI_R9_unused
&& in_attr[i].int_value() != elfcpp::AEABI_R9_unused) && in_attr[i].int_value() != elfcpp::AEABI_R9_unused
&& parameters->options().warn_mismatch())
{ {
gold_error(_("%s: conflicting use of R9"), name); gold_error(_("%s: conflicting use of R9"), name);
} }
@ -9602,11 +9648,12 @@ Target_arm<big_endian>::merge_object_attributes(
&& (in_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value() && (in_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value()
!= elfcpp::AEABI_R9_SB) != elfcpp::AEABI_R9_SB)
&& (out_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value() && (out_attr[elfcpp::Tag_ABI_PCS_R9_use].int_value()
!= elfcpp::AEABI_R9_unused)) != elfcpp::AEABI_R9_unused)
&& parameters->options().warn_mismatch())
{ {
gold_error(_("%s: SB relative addressing conflicts with use " gold_error(_("%s: SB relative addressing conflicts with use "
"of R9"), "of R9"),
name); name);
} }
// Use the smallest value specified. // Use the smallest value specified.
if (in_attr[i].int_value() < out_attr[i].int_value()) if (in_attr[i].int_value() < out_attr[i].int_value())
@ -9616,7 +9663,8 @@ Target_arm<big_endian>::merge_object_attributes(
// FIXME: Make it possible to turn off this warning. // FIXME: Make it possible to turn off this warning.
if (out_attr[i].int_value() if (out_attr[i].int_value()
&& in_attr[i].int_value() && in_attr[i].int_value()
&& out_attr[i].int_value() != in_attr[i].int_value()) && out_attr[i].int_value() != in_attr[i].int_value()
&& parameters->options().warn_mismatch())
{ {
gold_warning(_("%s uses %u-byte wchar_t yet the output is to " gold_warning(_("%s uses %u-byte wchar_t yet the output is to "
"use %u-byte wchar_t; use of wchar_t values " "use %u-byte wchar_t; use of wchar_t values "
@ -9639,7 +9687,8 @@ Target_arm<big_endian>::merge_object_attributes(
} }
// FIXME: Make it possible to turn off this warning. // FIXME: Make it possible to turn off this warning.
else if (in_attr[i].int_value() != elfcpp::AEABI_enum_forced_wide else if (in_attr[i].int_value() != elfcpp::AEABI_enum_forced_wide
&& out_attr[i].int_value() != in_attr[i].int_value()) && out_attr[i].int_value() != in_attr[i].int_value()
&& parameters->options().warn_mismatch())
{ {
unsigned int in_value = in_attr[i].int_value(); unsigned int in_value = in_attr[i].int_value();
unsigned int out_value = out_attr[i].int_value(); unsigned int out_value = out_attr[i].int_value();
@ -9656,7 +9705,8 @@ Target_arm<big_endian>::merge_object_attributes(
// Aready done. // Aready done.
break; break;
case elfcpp::Tag_ABI_WMMX_args: case elfcpp::Tag_ABI_WMMX_args:
if (in_attr[i].int_value() != out_attr[i].int_value()) if (in_attr[i].int_value() != out_attr[i].int_value()
&& parameters->options().warn_mismatch())
{ {
gold_error(_("%s uses iWMMXt register arguments, output does " gold_error(_("%s uses iWMMXt register arguments, output does "
"not"), "not"),
@ -9677,7 +9727,8 @@ Target_arm<big_endian>::merge_object_attributes(
case elfcpp::Tag_ABI_FP_16bit_format: case elfcpp::Tag_ABI_FP_16bit_format:
if (in_attr[i].int_value() != 0 && out_attr[i].int_value() != 0) if (in_attr[i].int_value() != 0 && out_attr[i].int_value() != 0)
{ {
if (in_attr[i].int_value() != out_attr[i].int_value()) if (in_attr[i].int_value() != out_attr[i].int_value()
&& parameters->options().warn_mismatch())
gold_error(_("fp16 format mismatch between %s and output"), gold_error(_("fp16 format mismatch between %s and output"),
name); name);
} }
@ -9714,7 +9765,8 @@ Target_arm<big_endian>::merge_object_attributes(
|| in_attr[i].string_value() != "") || in_attr[i].string_value() != "")
err_object = name; err_object = name;
if (err_object != NULL) if (err_object != NULL
&& parameters->options().warn_mismatch())
{ {
// Attribute numbers >=64 (mod 128) can be safely ignored. // Attribute numbers >=64 (mod 128) can be safely ignored.
if ((i & 127) < 64) if ((i & 127) < 64)
@ -9806,7 +9858,7 @@ Target_arm<big_endian>::merge_object_attributes(
} }
} }
if (err_object) if (err_object && parameters->options().warn_mismatch())
{ {
// Attribute numbers >=64 (mod 128) can be safely ignored. */ // Attribute numbers >=64 (mod 128) can be safely ignored. */
if ((err_tag & 127) < 64) if ((err_tag & 127) < 64)

View File

@ -532,13 +532,23 @@ queue_middle_tasks(const General_options& options,
} }
} }
// If we failed to open any input files, it's possible for
// THIS_BLOCKER to be NULL here. There's no real point in
// continuing if that happens.
if (this_blocker == NULL) if (this_blocker == NULL)
{ {
gold_assert(parameters->errors()->error_count() > 0); if (input_objects->number_of_relobjs() == 0)
gold_exit(false); {
// If we are given only archives in input, we have no regular
// objects and THIS_BLOCKER is NULL here. Create a dummy
// blocker here so that we can run the layout task immediately.
this_blocker = new Task_token(true);
}
else
{
// If we failed to open any input files, it's possible for
// THIS_BLOCKER to be NULL here. There's no real point in
// continuing if that happens.
gold_assert(parameters->errors()->error_count() > 0);
gold_exit(false);
}
} }
// When all those tasks are complete, we can start laying out the // When all those tasks are complete, we can start laying out the

View File

@ -614,6 +614,18 @@ General_options::parse_fix_v4bx_interworking(const char*, const char*,
this->fix_v4bx_ = FIX_V4BX_INTERWORKING; this->fix_v4bx_ = FIX_V4BX_INTERWORKING;
} }
void
General_options::parse_EB(const char*, const char*, Command_line*)
{
this->endianness_ = ENDIANNESS_BIG;
}
void
General_options::parse_EL(const char*, const char*, Command_line*)
{
this->endianness_ = ENDIANNESS_LITTLE;
}
} // End namespace gold. } // End namespace gold.
namespace namespace
@ -845,7 +857,8 @@ General_options::General_options()
excluded_libs_(), excluded_libs_(),
symbols_to_retain_(), symbols_to_retain_(),
section_starts_(), section_starts_(),
fix_v4bx_(FIX_V4BX_NONE) fix_v4bx_(FIX_V4BX_NONE),
endianness_(ENDIANNESS_NOT_SET)
{ {
// Turn off option registration once construction is complete. // Turn off option registration once construction is complete.
gold::options::ready_to_register = false; gold::options::ready_to_register = false;

View File

@ -713,9 +713,15 @@ class General_options
N_("Export all dynamic symbols"), N_("Export all dynamic symbols"),
N_("Do not export all dynamic symbols (default)")); N_("Do not export all dynamic symbols (default)"));
DEFINE_special(EB, options::ONE_DASH, '\0',
N_("Link big-endian objects."), NULL);
DEFINE_bool(eh_frame_hdr, options::TWO_DASHES, '\0', false, DEFINE_bool(eh_frame_hdr, options::TWO_DASHES, '\0', false,
N_("Create exception frame header"), NULL); N_("Create exception frame header"), NULL);
DEFINE_special(EL, options::ONE_DASH, '\0',
N_("Link little-endian objects."), NULL);
DEFINE_bool(fatal_warnings, options::TWO_DASHES, '\0', false, DEFINE_bool(fatal_warnings, options::TWO_DASHES, '\0', false,
N_("Treat warnings as errors"), N_("Treat warnings as errors"),
N_("Do not treat warnings as errors")); N_("Do not treat warnings as errors"));
@ -824,12 +830,18 @@ class General_options
DEFINE_string(oformat, options::EXACTLY_TWO_DASHES, '\0', "elf", DEFINE_string(oformat, options::EXACTLY_TWO_DASHES, '\0', "elf",
N_("Set output format"), N_("[binary]")); N_("Set output format"), N_("[binary]"));
DEFINE_bool(p, options::ONE_DASH, '\0', false,
N_("(ARM only) Ignore for backward compatibility"), NULL);
DEFINE_bool(pie, options::ONE_DASH, '\0', false, DEFINE_bool(pie, options::ONE_DASH, '\0', false,
N_("Create a position independent executable"), NULL); N_("Create a position independent executable"), NULL);
DEFINE_bool_alias(pic_executable, pie, options::TWO_DASHES, '\0', DEFINE_bool_alias(pic_executable, pie, options::TWO_DASHES, '\0',
N_("Create a position independent executable"), NULL, N_("Create a position independent executable"), NULL,
false); false);
DEFINE_bool(pipeline_knowledge, options::ONE_DASH, '\0', false,
NULL, N_("(ARM only) Ignore for backward compatibility"));
#ifdef ENABLE_PLUGINS #ifdef ENABLE_PLUGINS
DEFINE_special(plugin, options::TWO_DASHES, '\0', DEFINE_special(plugin, options::TWO_DASHES, '\0',
N_("Load a plugin library"), N_("PLUGIN")); N_("Load a plugin library"), N_("PLUGIN"));
@ -992,6 +1004,9 @@ class General_options
DEFINE_bool(warn_constructors, options::TWO_DASHES, '\0', false, DEFINE_bool(warn_constructors, options::TWO_DASHES, '\0', false,
N_("Ignored"), N_("Ignored")); N_("Ignored"), N_("Ignored"));
DEFINE_bool(warn_mismatch, options::TWO_DASHES, '\0', true,
NULL, N_("Don't warn about mismatched input files"));
DEFINE_bool(warn_multiple_gp, options::TWO_DASHES, '\0', false, DEFINE_bool(warn_multiple_gp, options::TWO_DASHES, '\0', false,
N_("Ignored"), NULL); N_("Ignored"), NULL);
@ -1256,6 +1271,17 @@ class General_options
fix_v4bx() const fix_v4bx() const
{ return (this->fix_v4bx_); } { return (this->fix_v4bx_); }
enum Endianness
{
ENDIANNESS_NOT_SET,
ENDIANNESS_BIG,
ENDIANNESS_LITTLE
};
Endianness
endianness() const
{ return this->endianness_; }
private: private:
// Don't copy this structure. // Don't copy this structure.
General_options(const General_options&); General_options(const General_options&);
@ -1347,6 +1373,8 @@ class General_options
std::map<std::string, uint64_t> section_starts_; std::map<std::string, uint64_t> section_starts_;
// Whether to process armv4 bx instruction relocation. // Whether to process armv4 bx instruction relocation.
Fix_v4bx fix_v4bx_; Fix_v4bx fix_v4bx_;
// Endianness.
Endianness endianness_;
}; };
// The position-dependent options. We use this to store the state of // The position-dependent options. We use this to store the state of

View File

@ -89,6 +89,8 @@ Parameters::set_options(const General_options* options)
// If --verbose is set, it acts as "--debug=files". // If --verbose is set, it acts as "--debug=files".
if (options->verbose()) if (options->verbose())
this->debug_ |= DEBUG_FILES; this->debug_ |= DEBUG_FILES;
if (this->target_valid())
this->check_target_endianness();
} }
void void
@ -113,6 +115,8 @@ Parameters::set_target_once(Target* target)
{ {
gold_assert(this->target_ == NULL); gold_assert(this->target_ == NULL);
this->target_ = target; this->target_ = target;
if (this->options_valid())
this->check_target_endianness();
} }
// Clear the target, for testing. // Clear the target, for testing.
@ -181,6 +185,29 @@ Parameters::size_and_endianness() const
gold_unreachable(); gold_unreachable();
} }
// If output endianness is specified in command line, check that it does
// not conflict with the target.
void
Parameters::check_target_endianness()
{
General_options::Endianness endianness = this->options().endianness();
if (endianness != General_options::ENDIANNESS_NOT_SET)
{
bool big_endian;
if (endianness == General_options::ENDIANNESS_BIG)
big_endian = true;
else
{
gold_assert(endianness == General_options::ENDIANNESS_LITTLE);
big_endian = false;;
}
if (this->target().is_big_endian() != big_endian)
gold_error(_("input file does not match -EB/EL option"));
}
}
void void
set_parameters_errors(Errors* errors) set_parameters_errors(Errors* errors)
{ static_parameters.set_errors(errors); } { static_parameters.set_errors(errors); }
@ -227,9 +254,18 @@ parameters_force_valid_target()
} }
// The GOLD_DEFAULT_xx macros are defined by the configure script. // The GOLD_DEFAULT_xx macros are defined by the configure script.
bool is_big_endian;
General_options::Endianness endianness = parameters->options().endianness();
if (endianness == General_options::ENDIANNESS_BIG)
is_big_endian = true;
else if (endianness == General_options::ENDIANNESS_LITTLE)
is_big_endian = false;
else
is_big_endian = GOLD_DEFAULT_BIG_ENDIAN;
Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE, Target* target = select_target(elfcpp::GOLD_DEFAULT_MACHINE,
GOLD_DEFAULT_SIZE, GOLD_DEFAULT_SIZE,
GOLD_DEFAULT_BIG_ENDIAN, is_big_endian,
elfcpp::GOLD_DEFAULT_OSABI, elfcpp::GOLD_DEFAULT_OSABI,
0); 0);
gold_assert(target != NULL); gold_assert(target != NULL);

View File

@ -149,6 +149,9 @@ class Parameters
void void
set_target_once(Target*); set_target_once(Target*);
void
check_target_endianness();
friend class Set_parameters_target_once; friend class Set_parameters_target_once;
Errors* errors_; Errors* errors_;

View File

@ -461,7 +461,7 @@ class Target
std::string*, std::string*) const; std::string*, std::string*) const;
// make_elf_object hooks. There are four versions of these for // make_elf_object hooks. There are four versions of these for
// different address sizes and endianities. // different address sizes and endianness.
// Set processor specific flags. // Set processor specific flags.
void void
@ -544,7 +544,7 @@ class Target
private: private:
// The implementations of the four do_make_elf_object virtual functions are // The implementations of the four do_make_elf_object virtual functions are
// almost identical except for their sizes and endianity. We use a template. // almost identical except for their sizes and endianness. We use a template.
// for their implementations. // for their implementations.
template<int size, bool big_endian> template<int size, bool big_endian>
inline Object* inline Object*