From: David S. Miller Date: Tue, 9 Feb 2010 20:29:44 +0000 (+0000) Subject: * output.h (Output_data_dynamic::add_section_size): New method X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=612a8d3dbf065f5fbaf7d9fe094a252ea6eb6c17;p=binutils-gdb.git * output.h (Output_data_dynamic::add_section_size): New method that takes two Output_data objects. (Output_data_dynamic::Dynamic_entry): Create storage for secondary entry param. Handle it in initializers. * output.cc (Output_data_dynamic::Dynamic_entry::write): For DYNAMIC_SECTION_SIZE, add in second object size if non-NULL. * layout.h (Layout::add_target_dynamic_tags): Add dynrel_includes_plt arg. * layout.cc (Layout::add_target_dynamic_tags): If dynrel_includes_plt, and .rela.plt exists, set DT_REL{,A}SZ to sum of .rela.dyn and .rela.plt * arm.cc (Target_arm::do_finalize_sections): Update to pass false for dynrel_includes_plt. * i386.cc (Target_i386::do_finalize_sections): Likewise. * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. * sparc.cc (Target_sparc::make_plt_entry): Force .rela.dyn to be output before .rela.plt (Target_sparc::do_finalize_sections): Update to pass true for dynrel_includes_plt. * powerpc.cc (Target_powerpc::make_plt_entry): Force .rela.dyn to be output before .rela.plt (Target_powerpc::do_finalize_sections): Update to pass true for dynrel_includes_plt when 32-bit. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index c2daecdd281..24b1b789155 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -4,6 +4,29 @@ R_SPARC_RELATIVE using ->add_local_relative(). (Target_sparc::Scan::global): Likewise for ->add_global_relative(). + * output.h (Output_data_dynamic::add_section_size): New method + that takes two Output_data objects. + (Output_data_dynamic::Dynamic_entry): Create storage for secondary + entry param. Handle it in initializers. + * output.cc (Output_data_dynamic::Dynamic_entry::write): For + DYNAMIC_SECTION_SIZE, add in second object size if non-NULL. + * layout.h (Layout::add_target_dynamic_tags): Add dynrel_includes_plt + arg. + * layout.cc (Layout::add_target_dynamic_tags): If dynrel_includes_plt, + and .rela.plt exists, set DT_REL{,A}SZ to sum of .rela.dyn and .rela.plt + * arm.cc (Target_arm::do_finalize_sections): Update to pass false + for dynrel_includes_plt. + * i386.cc (Target_i386::do_finalize_sections): Likewise. + * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. + * sparc.cc (Target_sparc::make_plt_entry): Force .rela.dyn to be output + before .rela.plt + (Target_sparc::do_finalize_sections): Update to pass true for + dynrel_includes_plt. + * powerpc.cc (Target_powerpc::make_plt_entry): Force .rela.dyn to be + output before .rela.plt + (Target_powerpc::do_finalize_sections): Update to pass true for + dynrel_includes_plt when 32-bit. + 2010-02-08 Doug Kwan * arm.cc (Arm_relobj::simple_input_section_output_address): New diff --git a/gold/arm.cc b/gold/arm.cc index f121f93fcf2..902805c3956 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -7094,7 +7094,7 @@ Target_arm::do_finalize_sections( ? NULL : this->plt_->rel_plt()); layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, - this->rel_dyn_, true); + this->rel_dyn_, true, false); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/i386.cc b/gold/i386.cc index 2eab3f86c08..f2a7b53f7ad 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1609,7 +1609,7 @@ Target_i386::do_finalize_sections( ? NULL : this->plt_->rel_plt()); layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, - this->rel_dyn_, true); + this->rel_dyn_, true, false); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/layout.cc b/gold/layout.cc index 52989a5b1a8..faa0c7252bc 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -3240,7 +3240,7 @@ void Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, const Output_data* plt_rel, const Output_data_reloc_generic* dyn_rel, - bool add_debug) + bool add_debug, bool dynrel_includes_plt) { Output_data_dynamic* odyn = this->dynamic_data_; if (odyn == NULL) @@ -3261,8 +3261,12 @@ Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, { odyn->add_section_address(use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA, dyn_rel); - odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ, - dyn_rel); + if (plt_rel != NULL && dynrel_includes_plt) + odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ, + dyn_rel, plt_rel); + else + odyn->add_section_size(use_rel ? elfcpp::DT_RELSZ : elfcpp::DT_RELASZ, + dyn_rel); const int size = parameters->target().get_size(); elfcpp::DT rel_tag; int rel_size; diff --git a/gold/layout.h b/gold/layout.h index 15e75484b34..cd15c983e8b 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -563,7 +563,7 @@ class Layout add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, const Output_data* plt_rel, const Output_data_reloc_generic* dyn_rel, - bool add_debug); + bool add_debug, bool dynrel_includes_plt); // Compute and write out the build ID if needed. void diff --git a/gold/output.cc b/gold/output.cc index a8f03e7ec4c..4b34b8b70b6 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1560,6 +1560,8 @@ Output_data_dynamic::Dynamic_entry::write( case DYNAMIC_SECTION_SIZE: val = this->u_.od->data_size(); + if (this->od2 != NULL) + val += this->od2->data_size(); break; case DYNAMIC_SYMBOL: diff --git a/gold/output.h b/gold/output.h index 60d57debfb8..a549b7435e8 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1997,6 +1997,12 @@ class Output_data_dynamic : public Output_section_data add_section_size(elfcpp::DT tag, const Output_data* od) { this->add_entry(Dynamic_entry(tag, od, true)); } + // Add a new dynamic entry with the total size of two output datas. + void + add_section_size(elfcpp::DT tag, const Output_data* od, + const Output_data* od2) + { this->add_entry(Dynamic_entry(tag, od, od2)); } + // Add a new dynamic entry with the address of a symbol. void add_symbol(elfcpp::DT tag, const Symbol* sym) @@ -2045,7 +2051,19 @@ class Output_data_dynamic : public Output_section_data offset_(section_size ? DYNAMIC_SECTION_SIZE : DYNAMIC_SECTION_ADDRESS) - { this->u_.od = od; } + { + this->u_.od = od; + this->od2 = NULL; + } + + // Create an entry with the size of two sections. + Dynamic_entry(elfcpp::DT tag, const Output_data* od, const Output_data* od2) + : tag_(tag), + offset_(DYNAMIC_SECTION_SIZE) + { + this->u_.od = od; + this->od2 = od2; + } // Create an entry with the address of a section plus a constant offset. Dynamic_entry(elfcpp::DT tag, const Output_data* od, unsigned int offset) @@ -2101,6 +2119,8 @@ class Output_data_dynamic : public Output_section_data // For DYNAMIC_STRING. const char* str; } u_; + // For DYNAMIC_SYMBOL with two sections. + const Output_data* od2; // The dynamic tag. elfcpp::DT tag_; // The type of entry (Classification) or offset within a section. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 83bb992b8a1..cc4678229e9 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -948,6 +948,11 @@ Target_powerpc::make_plt_entry(Symbol_table* symtab, // Create the GOT section first. this->got_section(symtab, layout); + // Ensure that .rela.dyn always appears before .rela.plt This is + // necessary due to how, on PowerPC and some other targets, .rela.dyn + // needs to include .rela.plt in it's range. + this->rela_dyn_section(layout); + this->plt_ = new Output_data_plt_powerpc(layout); layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC @@ -1556,7 +1561,7 @@ Target_powerpc::do_finalize_sections( ? NULL : this->plt_->rel_plt()); layout->add_target_dynamic_tags(false, this->plt_, rel_plt, - this->rela_dyn_, true); + this->rela_dyn_, true, size == 32); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/sparc.cc b/gold/sparc.cc index 503cd8bb6bd..234c5f5aa0a 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1369,6 +1369,11 @@ Target_sparc::make_plt_entry(Symbol_table* symtab, // Create the GOT sections first. this->got_section(symtab, layout); + // Ensure that .rela.dyn always appears before .rela.plt This is + // necessary due to how, on Sparc and some other targets, .rela.dyn + // needs to include .rela.plt in it's range. + this->rela_dyn_section(layout); + this->plt_ = new Output_data_plt_sparc(layout); layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC @@ -2338,7 +2343,7 @@ Target_sparc::do_finalize_sections( ? NULL : this->plt_->rel_plt()); layout->add_target_dynamic_tags(false, this->plt_, rel_plt, - this->rela_dyn_, true); + this->rela_dyn_, true, true); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 585a49995ee..fea2ec9b914 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1741,7 +1741,7 @@ Target_x86_64::do_finalize_sections( ? NULL : this->plt_->rela_plt()); layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt, - this->rela_dyn_, true); + this->rela_dyn_, true, false); // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data();