diff options
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/arm.cc | 38 | ||||
-rw-r--r-- | gold/i386.cc | 39 | ||||
-rw-r--r-- | gold/layout.cc | 77 | ||||
-rw-r--r-- | gold/layout.h | 7 | ||||
-rw-r--r-- | gold/output.h | 16 | ||||
-rw-r--r-- | gold/powerpc.cc | 36 | ||||
-rw-r--r-- | gold/sparc.cc | 36 | ||||
-rw-r--r-- | gold/x86_64.cc | 51 |
9 files changed, 151 insertions, 165 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index b974662..a96d079 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,21 @@ 2010-01-07 Ian Lance Taylor <iant@google.com> + * output.h (class Output_data): Add const version of + output_section and do_output_section. + (class Output_section_data): Add const version of + do_output_section. + (class Output_section): Likewise. + * layout.cc (Layout::add_target_dynamic_tags): New function. + * layout.h (class Layout): Update declarations. + * arm.cc (Target_arm::do_finalize_sections): Use + add_target_dynamic_tags. + * i386.cc (Target_i386::do_finalize_sections): Likewise. + * powerpc.cc (Target_powerpc::do_finalize_sections): Likewise. + * sparc.cc (Target_sparc::do_finalize_sections): Likewise. + * x86_64.cc (Target_x86_64::do_finalize_sections): Likewise. + +2010-01-07 Ian Lance Taylor <iant@google.com> + PR 11042 * copy-relocs.cc (Copy_relocs::emit_copy_reloc): Mark the dynamic object as needed. diff --git a/gold/arm.cc b/gold/arm.cc index b77adc7..087979b 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -4868,39 +4868,11 @@ Target_arm<big_endian>::do_finalize_sections( this->set_may_use_blx(true); // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->got_plt_ != NULL - && this->got_plt_->output_section() != NULL) - odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); - - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); - } - - if (this->rel_dyn_ != NULL - && this->rel_dyn_->output_section() != NULL) - { - const Output_data* od = this->rel_dyn_; - odyn->add_section_address(elfcpp::DT_REL, od); - odyn->add_section_size(elfcpp::DT_RELSZ, od); - odyn->add_constant(elfcpp::DT_RELENT, - elfcpp::Elf_sizes<32>::rel_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, + this->rel_dyn_, true); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/i386.cc b/gold/i386.cc index 1044ad8..e1b32e7 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -1565,40 +1565,11 @@ Target_i386::do_finalize_sections( const Input_objects*, Symbol_table* symtab) { - // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->got_plt_ != NULL - && this->got_plt_->output_section() != NULL) - odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); - - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); - } - - if (this->rel_dyn_ != NULL - && this->rel_dyn_->output_section() != NULL) - { - const Output_data* od = this->rel_dyn_; - odyn->add_section_address(elfcpp::DT_REL, od); - odyn->add_section_size(elfcpp::DT_RELSZ, od); - odyn->add_constant(elfcpp::DT_RELENT, - elfcpp::Elf_sizes<32>::rel_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(true, this->got_plt_, rel_plt, + this->rel_dyn_, true); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/layout.cc b/gold/layout.cc index 9f51e82..a55020c 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -3206,6 +3206,83 @@ Layout::create_interp(const Target* target) } } +// Add dynamic tags for the PLT and the dynamic relocs. This is +// called by the target-specific code. This does nothing if not doing +// a dynamic link. + +// USE_REL is true for REL relocs rather than RELA relocs. + +// If PLT_GOT is not NULL, then DT_PLTGOT points to it. + +// If PLT_REL is not NULL, it is used for DT_PLTRELSZ, and DT_JMPREL, +// and we also set DT_PLTREL. + +// If DYN_REL is not NULL, it is used for DT_REL/DT_RELA, +// DT_RELSZ/DT_RELASZ, DT_RELENT/DT_RELAENT. + +// If ADD_DEBUG is true, we add a DT_DEBUG entry when generating an +// executable. + +void +Layout::add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, + const Output_data* plt_rel, + const Output_data* dyn_rel, bool add_debug) +{ + Output_data_dynamic* odyn = this->dynamic_data_; + if (odyn == NULL) + return; + + if (plt_got != NULL && plt_got->output_section() != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, plt_got); + + if (plt_rel != NULL && plt_rel->output_section() != NULL) + { + odyn->add_section_size(elfcpp::DT_PLTRELSZ, plt_rel); + odyn->add_section_address(elfcpp::DT_JMPREL, plt_rel); + odyn->add_constant(elfcpp::DT_PLTREL, + use_rel ? elfcpp::DT_REL : elfcpp::DT_RELA); + } + + if (dyn_rel != NULL && dyn_rel->output_section() != NULL) + { + 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); + const int size = parameters->target().get_size(); + elfcpp::DT rel_tag; + int rel_size; + if (use_rel) + { + rel_tag = elfcpp::DT_RELENT; + if (size == 32) + rel_size = Reloc_types<elfcpp::SHT_REL, 32, false>::reloc_size; + else if (size == 64) + rel_size = Reloc_types<elfcpp::SHT_REL, 64, false>::reloc_size; + else + gold_unreachable(); + } + else + { + rel_tag = elfcpp::DT_RELAENT; + if (size == 32) + rel_size = Reloc_types<elfcpp::SHT_RELA, 32, false>::reloc_size; + else if (size == 64) + rel_size = Reloc_types<elfcpp::SHT_RELA, 64, false>::reloc_size; + else + gold_unreachable(); + } + odyn->add_constant(rel_tag, rel_size); + } + + if (add_debug && !parameters->options().shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } +} + // Finish the .dynamic section and PT_DYNAMIC segment. void diff --git a/gold/layout.h b/gold/layout.h index 604f19b..0b16cdf 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -556,6 +556,13 @@ class Layout incremental_inputs() { return this->incremental_inputs_; } + // For the target-specific code to add dynamic tags which are common + // to most targets. + void + add_target_dynamic_tags(bool use_rel, const Output_data* plt_got, + const Output_data* plt_rel, + const Output_data* dyn_rel, bool add_debug); + // Compute and write out the build ID if needed. void write_build_id(Output_file*) const; diff --git a/gold/output.h b/gold/output.h index 98132e9..18e0a9e 100644 --- a/gold/output.h +++ b/gold/output.h @@ -206,6 +206,10 @@ class Output_data output_section() { return this->do_output_section(); } + const Output_section* + output_section() const + { return this->do_output_section(); } + // Return the output section index, if there is an output section. unsigned int out_shndx() const @@ -358,6 +362,10 @@ class Output_data do_output_section() { return NULL; } + virtual const Output_section* + do_output_section() const + { return NULL; } + // Return the output section index, if there is an output section. virtual unsigned int do_out_shndx() const @@ -746,6 +754,10 @@ class Output_section_data : public Output_data do_output_section() { return this->output_section_; } + const Output_section* + do_output_section() const + { return this->output_section_; } + // Return the section index of the output section. unsigned int do_out_shndx() const; @@ -2641,6 +2653,10 @@ class Output_section : public Output_data do_output_section() { return this; } + const Output_section* + do_output_section() const + { return this; } + // Return the section index in the output file. unsigned int do_out_shndx() const diff --git a/gold/powerpc.cc b/gold/powerpc.cc index f7e62e7..83bb992 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -1552,37 +1552,11 @@ Target_powerpc<size, big_endian>::do_finalize_sections( Symbol_table*) { // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - - odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); - } - - if (this->rela_dyn_ != NULL - && this->rela_dyn_->output_section() != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<size>::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->plt_, rel_plt, + this->rela_dyn_, true); // Emit any relocs we saved in an attempt to avoid generating COPY // relocs. diff --git a/gold/sparc.cc b/gold/sparc.cc index 841db2f..c5ce06a 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -2331,37 +2331,11 @@ Target_sparc<size, big_endian>::do_finalize_sections( Symbol_table*) { // Fill in some more dynamic tags. - Output_data_dynamic* const odyn = layout->dynamic_data(); - if (odyn != NULL) - { - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - - odyn->add_section_address(elfcpp::DT_PLTGOT, this->plt_); - } - - if (this->rela_dyn_ != NULL - && this->rela_dyn_->output_section() != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<size>::rela_size); - } - - if (!parameters->options().shared()) - { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); - } - } + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->plt_, rel_plt, + this->rela_dyn_, 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 a7e7a39..f0aade4 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -1655,48 +1655,27 @@ Target_x86_64::do_finalize_sections( const Input_objects*, Symbol_table* symtab) { + const Reloc_section* rel_plt = (this->plt_ == NULL + ? NULL + : this->plt_->rel_plt()); + layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt, + this->rela_dyn_, true); + // Fill in some more dynamic tags. Output_data_dynamic* const odyn = layout->dynamic_data(); if (odyn != NULL) { - if (this->got_plt_ != NULL - && this->got_plt_->output_section() != NULL) - odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); - if (this->plt_ != NULL - && this->plt_->output_section() != NULL) - { - const Output_data* od = this->plt_->rel_plt(); - odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); - odyn->add_section_address(elfcpp::DT_JMPREL, od); - odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_RELA); - if (this->plt_->has_tlsdesc_entry()) - { - unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); - unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); - this->got_->finalize_data_size(); - odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, - this->plt_, plt_offset); - odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, - this->got_, got_offset); - } - } - - if (this->rela_dyn_ != NULL - && this->rela_dyn_->output_section() != NULL) - { - const Output_data* od = this->rela_dyn_; - odyn->add_section_address(elfcpp::DT_RELA, od); - odyn->add_section_size(elfcpp::DT_RELASZ, od); - odyn->add_constant(elfcpp::DT_RELAENT, - elfcpp::Elf_sizes<64>::rela_size); - } - - if (!parameters->options().shared()) + && this->plt_->output_section() != NULL + && this->plt_->has_tlsdesc_entry()) { - // The value of the DT_DEBUG tag is filled in by the dynamic - // linker at run time, and used by the debugger. - odyn->add_constant(elfcpp::DT_DEBUG, 0); + unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset(); + unsigned int got_offset = this->plt_->get_tlsdesc_got_offset(); + this->got_->finalize_data_size(); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT, + this->plt_, plt_offset); + odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT, + this->got_, got_offset); } } |