From a8ecc9fe61d0fdb1f694c5f3fac910802468d43f Mon Sep 17 00:00:00 2001 From: Vladimir Radosavljevic Date: Mon, 20 Jun 2016 12:10:53 -0700 Subject: [PATCH] Add support for MIPS .rld_map section. Includes DT_MIPS_RLD_MAP and DT_MIPS_RLD_MAP_REL dynamic tags and __RLD_MAP symbol. 2016-06-20 Vladimir Radosavljevic elfcpp/ * elfcpp.h (DT_MIPS_RLD_MAP_REL): New enum constant. gold/ * mips.cc (Target_mips::Target_mips): Initialize rld_map_. (Target_mips::rld_map_): New data member. (Target_mips::do_finalize_sections): Add support for DT_MIPS_RLD_MAP and DT_MIPS_RLD_MAP_REL dynamic tags, .rld_map section, and __RLD_MAP symbol. (Target_mips::do_dynamic_tag_custom_value): Add support for DT_MIPS_RLD_MAP_REL dynamic tag. * output.cc (Output_data_dynamic::get_entry_offset): New method definition. * output.h (Output_data_dynamic::get_entry_offset): New method declaration. --- elfcpp/ChangeLog | 4 ++++ elfcpp/elfcpp.h | 2 ++ gold/ChangeLog | 14 +++++++++++++ gold/mips.cc | 51 +++++++++++++++++++++++++++++++++++++++++++----- gold/output.cc | 21 ++++++++++++++++++++ gold/output.h | 4 ++++ 6 files changed, 91 insertions(+), 5 deletions(-) diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog index fa8594ee6da..62e21b5e795 100644 --- a/elfcpp/ChangeLog +++ b/elfcpp/ChangeLog @@ -1,3 +1,7 @@ +2016-06-20 Vladimir Radosavljevic + + * elfcpp.h (DT_MIPS_RLD_MAP_REL): New enum constant. + 2016-06-20 Vladimir Radosavljevic * mips.h (R_MIPS_PC21_S2, R_MIPS_PC26_S2, R_MIPS_PC18_S3, diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index f39a135ab37..7469bd8fd95 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -868,6 +868,8 @@ enum DT DT_MIPS_PLTGOT = 0x70000032, // Points to the base of a writable PLT. DT_MIPS_RWPLT = 0x70000034, + // Relative offset of run time loader map, used for debugging. + DT_MIPS_RLD_MAP_REL = 0x70000035, DT_AUXILIARY = 0x7ffffffd, DT_USED = 0x7ffffffe, diff --git a/gold/ChangeLog b/gold/ChangeLog index cf8289bba7a..a4c9d6c8fa0 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,17 @@ +2016-06-20 Vladimir Radosavljevic + + * mips.cc (Target_mips::Target_mips): Initialize rld_map_. + (Target_mips::rld_map_): New data member. + (Target_mips::do_finalize_sections): Add support for + DT_MIPS_RLD_MAP and DT_MIPS_RLD_MAP_REL dynamic tags, + .rld_map section, and __RLD_MAP symbol. + (Target_mips::do_dynamic_tag_custom_value): Add support for + DT_MIPS_RLD_MAP_REL dynamic tag. + * output.cc (Output_data_dynamic::get_entry_offset): New method + definition. + * output.h (Output_data_dynamic::get_entry_offset): New method + declaration. + 2016-06-20 Vladimir Radosavljevic * mips.cc (Mips_relocate_functions::relpc16): Add unaligned check. diff --git a/gold/mips.cc b/gold/mips.cc index e2b7855bfce..8893e315dd5 100644 --- a/gold/mips.cc +++ b/gold/mips.cc @@ -3292,10 +3292,10 @@ class Target_mips : public Sized_target public: Target_mips(const Target::Target_info* info = &mips_info) : Sized_target(info), got_(NULL), gp_(NULL), plt_(NULL), - got_plt_(NULL), rel_dyn_(NULL), copy_relocs_(), dyn_relocs_(), - la25_stub_(NULL), mips_mach_extensions_(), mips_stubs_(NULL), - attributes_section_data_(NULL), abiflags_(NULL), mach_(0), layout_(NULL), - got16_addends_(), has_abiflags_section_(false), + got_plt_(NULL), rel_dyn_(NULL), rld_map_(NULL), copy_relocs_(), + dyn_relocs_(), la25_stub_(NULL), mips_mach_extensions_(), + mips_stubs_(NULL), attributes_section_data_(NULL), abiflags_(NULL), + mach_(0), layout_(NULL), got16_addends_(), has_abiflags_section_(false), entry_symbol_is_compressed_(false), insn32_(false) { this->add_machine_extensions(); @@ -4181,6 +4181,8 @@ class Target_mips : public Sized_target Output_data_space* got_plt_; // The dynamic reloc section. Reloc_section* rel_dyn_; + // The .rld_map section. + Output_data_zero_fill* rld_map_; // Relocs saved to avoid a COPY reloc. Mips_copy_relocs copy_relocs_; @@ -9760,8 +9762,37 @@ Target_mips::do_finalize_sections(Layout* layout, if (this->plt_ != NULL) // DT_MIPS_PLTGOT dynamic tag odyn->add_section_address(elfcpp::DT_MIPS_PLTGOT, this->got_plt_); + + if (!parameters->options().shared()) + { + this->rld_map_ = new Output_data_zero_fill(size / 8, size / 8); + + layout->add_output_section_data(".rld_map", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), + this->rld_map_, ORDER_INVALID, false); + + // __RLD_MAP will be filled in by the runtime loader to contain + // a pointer to the _r_debug structure. + Symbol* rld_map = symtab->define_in_output_data("__RLD_MAP", NULL, + Symbol_table::PREDEFINED, + this->rld_map_, + 0, 0, elfcpp::STT_OBJECT, + elfcpp::STB_GLOBAL, + elfcpp::STV_DEFAULT, 0, + false, false); + + rld_map->set_needs_dynsym_entry(); + + if (!parameters->options().pie()) + // This member holds the absolute address of the debug pointer. + odyn->add_section_address(elfcpp::DT_MIPS_RLD_MAP, this->rld_map_); + else + // This member holds the offset to the debug pointer, + // relative to the address of the tag. + odyn->add_custom(elfcpp::DT_MIPS_RLD_MAP_REL); + } } - } +} // Get the custom dynamic tag value. template @@ -9797,6 +9828,16 @@ Target_mips::do_dynamic_tag_custom_value(elfcpp::DT tag) const return this->get_dt_mips_symtabno(); } + case elfcpp::DT_MIPS_RLD_MAP_REL: + { + // The MIPS_RLD_MAP_REL tag stores the offset to the debug pointer, + // relative to the address of the tag. + Output_data_dynamic* const odyn = this->layout_->dynamic_data(); + unsigned int entry_offset = + odyn->get_entry_offset(elfcpp::DT_MIPS_RLD_MAP_REL); + gold_assert(entry_offset != -1U); + return this->rld_map_->address() - (odyn->address() + entry_offset); + } default: gold_error(_("Unknown dynamic tag 0x%x"), (unsigned int)tag); } diff --git a/gold/output.cc b/gold/output.cc index 077e2c4481e..0a9e58f71d2 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1882,6 +1882,27 @@ Output_data_dynamic::do_adjust_output_section(Output_section* os) gold_unreachable(); } +// Get a dynamic entry offset. + +unsigned int +Output_data_dynamic::get_entry_offset(elfcpp::DT tag) const +{ + int dyn_size; + + if (parameters->target().get_size() == 32) + dyn_size = elfcpp::Elf_sizes<32>::dyn_size; + else if (parameters->target().get_size() == 64) + dyn_size = elfcpp::Elf_sizes<64>::dyn_size; + else + gold_unreachable(); + + for (size_t i = 0; i < entries_.size(); ++i) + if (entries_[i].tag() == tag) + return i * dyn_size; + + return -1U; +} + // Set the final data size. void diff --git a/gold/output.h b/gold/output.h index 0b96a03dddb..d8a8aaaaba7 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2781,6 +2781,10 @@ class Output_data_dynamic : public Output_section_data add_custom(elfcpp::DT tag) { this->add_entry(Dynamic_entry(tag)); } + // Get a dynamic entry offset. + unsigned int + get_entry_offset(elfcpp::DT tag) const; + protected: // Adjust the output section to set the entry size. void -- 2.30.2