aboutsummaryrefslogtreecommitdiff
path: root/elfcpp
diff options
context:
space:
mode:
Diffstat (limited to 'elfcpp')
-rw-r--r--elfcpp/ChangeLog6
-rw-r--r--elfcpp/elfcpp.h166
-rw-r--r--elfcpp/elfcpp_internal.h23
3 files changed, 195 insertions, 0 deletions
diff --git a/elfcpp/ChangeLog b/elfcpp/ChangeLog
index e48be00..198eb92 100644
--- a/elfcpp/ChangeLog
+++ b/elfcpp/ChangeLog
@@ -1,3 +1,9 @@
+2016-01-11 Cary Coutant <ccoutant@gmail.com>
+
+ * elfcpp.h (Mips64_rel, Mips64_rel_write): New classes.
+ (Mips64_rela, Mips64_rela_write): New classes.
+ * elfcpp_internal.h (Mips64_rel_data, Mips64_rela_data): New structs.
+
2016-01-01 Alan Modra <amodra@gmail.com>
Update year range in copyright notice of all files.
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h
index e0eae42..3d7039a 100644
--- a/elfcpp/elfcpp.h
+++ b/elfcpp/elfcpp.h
@@ -1661,6 +1661,172 @@ class Rela_write
internal::Rela_data<size>* p_;
};
+// MIPS-64 has a non-standard relocation layout.
+
+template<bool big_endian>
+class Mips64_rel
+{
+ public:
+ Mips64_rel(const unsigned char* p)
+ : p_(reinterpret_cast<const internal::Mips64_rel_data*>(p))
+ { }
+
+ template<typename File>
+ Mips64_rel(File* file, typename File::Location loc)
+ : p_(reinterpret_cast<const internal::Mips64_rel_data*>(
+ file->view(loc.file_offset, loc.data_size).data()))
+ { }
+
+ typename Elf_types<64>::Elf_Addr
+ get_r_offset() const
+ { return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
+
+ Elf_Word
+ get_r_sym() const
+ { return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
+
+ unsigned char
+ get_r_ssym() const
+ { return this->p_->r_ssym; }
+
+ unsigned char
+ get_r_type() const
+ { return this->p_->r_type; }
+
+ unsigned char
+ get_r_type2() const
+ { return this->p_->r_type2; }
+
+ unsigned char
+ get_r_type3() const
+ { return this->p_->r_type3; }
+
+ private:
+ const internal::Mips64_rel_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rel_write
+{
+ public:
+ Mips64_rel_write(unsigned char* p)
+ : p_(reinterpret_cast<internal::Mips64_rel_data*>(p))
+ { }
+
+ void
+ put_r_offset(typename Elf_types<64>::Elf_Addr v)
+ { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
+
+ void
+ put_r_sym(Elf_Word v)
+ { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
+
+ void
+ put_r_ssym(unsigned char v)
+ { this->p_->r_ssym = v; }
+
+ void
+ put_r_type(unsigned char v)
+ { this->p_->r_type = v; }
+
+ void
+ put_r_type2(unsigned char v)
+ { this->p_->r_type2 = v; }
+
+ void
+ put_r_type3(unsigned char v)
+ { this->p_->r_type3 = v; }
+
+ private:
+ internal::Mips64_rel_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rela
+{
+ public:
+ Mips64_rela(const unsigned char* p)
+ : p_(reinterpret_cast<const internal::Mips64_rela_data*>(p))
+ { }
+
+ template<typename File>
+ Mips64_rela(File* file, typename File::Location loc)
+ : p_(reinterpret_cast<const internal::Mips64_rela_data*>(
+ file->view(loc.file_offset, loc.data_size).data()))
+ { }
+
+ typename Elf_types<64>::Elf_Addr
+ get_r_offset() const
+ { return Convert<64, big_endian>::convert_host(this->p_->r_offset); }
+
+ Elf_Word
+ get_r_sym() const
+ { return Convert<32, big_endian>::convert_host(this->p_->r_sym); }
+
+ unsigned char
+ get_r_ssym() const
+ { return this->p_->r_ssym; }
+
+ unsigned char
+ get_r_type() const
+ { return this->p_->r_type; }
+
+ unsigned char
+ get_r_type2() const
+ { return this->p_->r_type2; }
+
+ unsigned char
+ get_r_type3() const
+ { return this->p_->r_type3; }
+
+ typename Elf_types<64>::Elf_Swxword
+ get_r_addend() const
+ { return Convert<64, big_endian>::convert_host(this->p_->r_addend); }
+
+ private:
+ const internal::Mips64_rela_data* p_;
+};
+
+template<bool big_endian>
+class Mips64_rela_write
+{
+ public:
+ Mips64_rela_write(unsigned char* p)
+ : p_(reinterpret_cast<internal::Mips64_rela_data*>(p))
+ { }
+
+ void
+ put_r_offset(typename Elf_types<64>::Elf_Addr v)
+ { this->p_->r_offset = Convert<64, big_endian>::convert_host(v); }
+
+ void
+ put_r_sym(Elf_Word v)
+ { this->p_->r_sym = Convert<32, big_endian>::convert_host(v); }
+
+ void
+ put_r_ssym(unsigned char v)
+ { this->p_->r_ssym = v; }
+
+ void
+ put_r_type(unsigned char v)
+ { this->p_->r_type = v; }
+
+ void
+ put_r_type2(unsigned char v)
+ { this->p_->r_type2 = v; }
+
+ void
+ put_r_type3(unsigned char v)
+ { this->p_->r_type3 = v; }
+
+ void
+ put_r_addend(typename Elf_types<64>::Elf_Swxword v)
+ { this->p_->r_addend = Convert<64, big_endian>::convert_host(v); }
+
+ private:
+ internal::Mips64_rela_data* p_;
+};
+
// Accessor classes for entries in the ELF SHT_DYNAMIC section aka
// PT_DYNAMIC segment.
diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h
index 7080a2d..edca55f 100644
--- a/elfcpp/elfcpp_internal.h
+++ b/elfcpp/elfcpp_internal.h
@@ -180,6 +180,29 @@ struct Rela_data
typename Elf_types<size>::Elf_Swxword r_addend;
};
+// MIPS-64 has a non-standard layout for relocations.
+
+struct Mips64_rel_data
+{
+ typename Elf_types<64>::Elf_Addr r_offset;
+ Elf_Word r_sym;
+ unsigned char r_ssym;
+ unsigned char r_type3;
+ unsigned char r_type2;
+ unsigned char r_type;
+};
+
+struct Mips64_rela_data
+{
+ typename Elf_types<64>::Elf_Addr r_offset;
+ Elf_Word r_sym;
+ unsigned char r_ssym;
+ unsigned char r_type3;
+ unsigned char r_type2;
+ unsigned char r_type;
+ typename Elf_types<64>::Elf_Swxword r_addend;
+};
+
// An entry in the ELF SHT_DYNAMIC section aka PT_DYNAMIC segment.
template<int size>