aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorVladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>2016-06-20 12:10:53 -0700
committerCary Coutant <ccoutant@gmail.com>2016-06-20 12:16:26 -0700
commita8ecc9fe61d0fdb1f694c5f3fac910802468d43f (patch)
tree51bfde2464642854b5c74f29b5f0cb0b392f7df4 /gold
parentbeceef50438ccf2917744147a4fdadcc84db7d78 (diff)
downloadgdb-a8ecc9fe61d0fdb1f694c5f3fac910802468d43f.zip
gdb-a8ecc9fe61d0fdb1f694c5f3fac910802468d43f.tar.gz
gdb-a8ecc9fe61d0fdb1f694c5f3fac910802468d43f.tar.bz2
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 <Vladimir.Radosavljevic@imgtec.com> 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.
Diffstat (limited to 'gold')
-rw-r--r--gold/ChangeLog14
-rw-r--r--gold/mips.cc51
-rw-r--r--gold/output.cc21
-rw-r--r--gold/output.h4
4 files changed, 85 insertions, 5 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index cf8289b..a4c9d6c 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,5 +1,19 @@
2016-06-20 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
+ * 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 <Vladimir.Radosavljevic@imgtec.com>
+
* mips.cc (Mips_relocate_functions::relpc16): Add unaligned check.
2016-06-20 Vladimir Radosavljevic <Vladimir.Radosavljevic@imgtec.com>
diff --git a/gold/mips.cc b/gold/mips.cc
index e2b7855..8893e31 100644
--- a/gold/mips.cc
+++ b/gold/mips.cc
@@ -3292,10 +3292,10 @@ class Target_mips : public Sized_target<size, big_endian>
public:
Target_mips(const Target::Target_info* info = &mips_info)
: Sized_target<size, big_endian>(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<size, big_endian>
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<elfcpp::SHT_REL, size, big_endian> copy_relocs_;
@@ -9760,8 +9762,37 @@ Target_mips<size, big_endian>::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<int size, bool big_endian>
@@ -9797,6 +9828,16 @@ Target_mips<size, big_endian>::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 077e2c4..0a9e58f 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 0b96a03..d8a8aaa 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