From 8d9455b422d98d97f090923445aa2680e6882f20 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 6 Nov 2006 22:45:08 +0000 Subject: [PATCH] Rework swapping code. --- elfcpp/elfcpp.h | 169 +++++++++---------- elfcpp/elfcpp_internal.h | 159 ------------------ elfcpp/elfcpp_swap.h | 350 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 426 insertions(+), 252 deletions(-) create mode 100644 elfcpp/elfcpp_swap.h diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index 3ae005ddc04..d92b46d382b 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -6,6 +6,7 @@ #define ELFCPP_H #include "elfcpp_config.h" +#include "elfcpp_swap.h" #include @@ -559,24 +560,6 @@ struct Elf_sizes static const int rela_size = sizeof(internal::Rela_data); }; -// Given the address of an Elf_Word, return the value. - -template -inline Elf_Word -read_elf_word(const Elf_Word* p) -{ - return internal::convert_word(*p); -} - -// Store an Elf_Word into an address. - -template -inline void -write_elf_word(Elf_Word* p, Elf_Word v) -{ - *p = internal::convert_word(v); -} - // Accessor class for the ELF file header. template @@ -593,55 +576,55 @@ class Ehdr Elf_Half get_e_type() const - { return internal::convert_half(this->p_->e_type); } + { return Convert<16, big_endian>::convert_host(this->p_->e_type); } Elf_Half get_e_machine() const - { return internal::convert_half(this->p_->e_machine); } + { return Convert<16, big_endian>::convert_host(this->p_->e_machine); } Elf_Word get_e_version() const - { return internal::convert_word(this->p_->e_version); } + { return Convert<32, big_endian>::convert_host(this->p_->e_version); } typename Elf_types::Elf_Addr get_e_entry() const - { return internal::convert_addr(this->p_->e_entry); } + { return Convert::convert_host(this->p_->e_entry); } typename Elf_types::Elf_Off get_e_phoff() const - { return internal::convert_off(this->p_->e_phoff); } + { return Convert::convert_host(this->p_->e_phoff); } typename Elf_types::Elf_Off get_e_shoff() const - { return internal::convert_off(this->p_->e_shoff); } + { return Convert::convert_host(this->p_->e_shoff); } Elf_Word get_e_flags() const - { return internal::convert_word(this->p_->e_flags); } + { return Convert<32, big_endian>::convert_host(this->p_->e_flags); } Elf_Half get_e_ehsize() const - { return internal::convert_half(this->p_->e_ehsize); } + { return Convert<16, big_endian>::convert_host(this->p_->e_ehsize); } Elf_Half get_e_phentsize() const - { return internal::convert_half(this->p_->e_phentsize); } + { return Convert<16, big_endian>::convert_host(this->p_->e_phentsize); } Elf_Half get_e_phnum() const - { return internal::convert_half(this->p_->e_phnum); } + { return Convert<16, big_endian>::convert_host(this->p_->e_phnum); } Elf_Half get_e_shentsize() const - { return internal::convert_half(this->p_->e_shentsize); } + { return Convert<16, big_endian>::convert_host(this->p_->e_shentsize); } Elf_Half get_e_shnum() const - { return internal::convert_half(this->p_->e_shnum); } + { return Convert<16, big_endian>::convert_host(this->p_->e_shnum); } Elf_Half get_e_shstrndx() const - { return internal::convert_half(this->p_->e_shstrndx); } + { return Convert<16, big_endian>::convert_host(this->p_->e_shstrndx); } private: const internal::Ehdr_data* p_; @@ -663,55 +646,55 @@ class Ehdr_write void put_e_type(Elf_Half v) - { this->p_->e_type = internal::convert_half(v); } + { this->p_->e_type = Convert<16, big_endian>::convert_host(v); } void put_e_machine(Elf_Half v) - { this->p_->e_machine = internal::convert_half(v); } + { this->p_->e_machine = Convert<16, big_endian>::convert_host(v); } void put_e_version(Elf_Word v) - { this->p_->e_version = internal::convert_word(v); } + { this->p_->e_version = Convert<32, big_endian>::convert_host(v); } void put_e_entry(typename Elf_types::Elf_Addr v) - { this->p_->e_entry = internal::convert_addr(v); } + { this->p_->e_entry = Convert::convert_host(v); } void put_e_phoff(typename Elf_types::Elf_Off v) - { this->p_->e_phoff = internal::convert_off(v); } + { this->p_->e_phoff = Convert::convert_host(v); } void put_e_shoff(typename Elf_types::Elf_Off v) - { this->p_->e_shoff = internal::convert_off(v); } + { this->p_->e_shoff = Convert::convert_host(v); } void put_e_flags(Elf_Word v) - { this->p_->e_flags = internal::convert_word(v); } + { this->p_->e_flags = Convert<32, big_endian>::convert_host(v); } void put_e_ehsize(Elf_Half v) - { this->p_->e_ehsize = internal::convert_half(v); } + { this->p_->e_ehsize = Convert<16, big_endian>::convert_host(v); } void put_e_phentsize(Elf_Half v) - { this->p_->e_phentsize = internal::convert_half(v); } + { this->p_->e_phentsize = Convert<16, big_endian>::convert_host(v); } void put_e_phnum(Elf_Half v) - { this->p_->e_phnum = internal::convert_half(v); } + { this->p_->e_phnum = Convert<16, big_endian>::convert_host(v); } void put_e_shentsize(Elf_Half v) - { this->p_->e_shentsize = internal::convert_half(v); } + { this->p_->e_shentsize = Convert<16, big_endian>::convert_host(v); } void put_e_shnum(Elf_Half v) - { this->p_->e_shnum = internal::convert_half(v); } + { this->p_->e_shnum = Convert<16, big_endian>::convert_host(v); } void put_e_shstrndx(Elf_Half v) - { this->p_->e_shstrndx = internal::convert_half(v); } + { this->p_->e_shstrndx = Convert<16, big_endian>::convert_host(v); } private: internal::Ehdr_data* p_; @@ -729,44 +712,44 @@ class Shdr Elf_Word get_sh_name() const - { return internal::convert_word(this->p_->sh_name); } + { return Convert<32, big_endian>::convert_host(this->p_->sh_name); } Elf_Word get_sh_type() const - { return internal::convert_word(this->p_->sh_type); } + { return Convert<32, big_endian>::convert_host(this->p_->sh_type); } typename Elf_types::Elf_WXword get_sh_flags() const - { return internal::convert_wxword(this->p_->sh_flags); } + { return Convert::convert_host(this->p_->sh_flags); } typename Elf_types::Elf_Addr get_sh_addr() const - { return internal::convert_addr(this->p_->sh_addr); } + { return Convert::convert_host(this->p_->sh_addr); } typename Elf_types::Elf_Off get_sh_offset() const - { return internal::convert_off(this->p_->sh_offset); } + { return Convert::convert_host(this->p_->sh_offset); } typename Elf_types::Elf_WXword get_sh_size() const - { return internal::convert_wxword(this->p_->sh_size); } + { return Convert::convert_host(this->p_->sh_size); } Elf_Word get_sh_link() const - { return internal::convert_word(this->p_->sh_link); } + { return Convert<32, big_endian>::convert_host(this->p_->sh_link); } Elf_Word get_sh_info() const - { return internal::convert_word(this->p_->sh_info); } + { return Convert<32, big_endian>::convert_host(this->p_->sh_info); } typename Elf_types::Elf_WXword get_sh_addralign() const { return - internal::convert_wxword(this->p_->sh_addralign); } + Convert::convert_host(this->p_->sh_addralign); } typename Elf_types::Elf_WXword get_sh_entsize() const - { return internal::convert_wxword(this->p_->sh_entsize); } + { return Convert::convert_host(this->p_->sh_entsize); } private: const internal::Shdr_data* p_; @@ -784,43 +767,43 @@ class Shdr_write void put_sh_name(Elf_Word v) - { this->p_->sh_name = internal::convert_word(v); } + { this->p_->sh_name = Convert<32, big_endian>::convert_host(v); } void put_sh_type(Elf_Word v) - { this->p_->sh_type = internal::convert_word(v); } + { this->p_->sh_type = Convert<32, big_endian>::convert_host(v); } void put_sh_flags(typename Elf_types::Elf_WXword v) - { this->p_->sh_flags = internal::convert_wxword(v); } + { this->p_->sh_flags = Convert::convert_host(v); } void put_sh_addr(typename Elf_types::Elf_Addr v) - { this->p_->sh_addr = internal::convert_addr(v); } + { this->p_->sh_addr = Convert::convert_host(v); } void put_sh_offset(typename Elf_types::Elf_Off v) - { this->p_->sh_offset = internal::convert_off(v); } + { this->p_->sh_offset = Convert::convert_host(v); } void put_sh_size(typename Elf_types::Elf_WXword v) - { this->p_->sh_size = internal::convert_wxword(v); } + { this->p_->sh_size = Convert::convert_host(v); } void put_sh_link(Elf_Word v) - { this->p_->sh_link = internal::convert_word(v); } + { this->p_->sh_link = Convert<32, big_endian>::convert_host(v); } void put_sh_info(Elf_Word v) - { this->p_->sh_info = internal::convert_word(v); } + { this->p_->sh_info = Convert<32, big_endian>::convert_host(v); } void put_sh_addralign(typename Elf_types::Elf_WXword v) - { this->p_->sh_addralign = internal::convert_wxword(v); } + { this->p_->sh_addralign = Convert::convert_host(v); } void put_sh_entsize(typename Elf_types::Elf_WXword v) - { this->p_->sh_entsize = internal::convert_wxword(v); } + { this->p_->sh_entsize = Convert::convert_host(v); } private: internal::Shdr_data* p_; @@ -838,35 +821,35 @@ class Phdr Elf_Word get_p_type() const - { return internal::convert_word(this->p_->p_type); } + { return Convert<32, big_endian>::convert_host(this->p_->p_type); } typename Elf_types::Elf_Off get_p_offset() const - { return internal::convert_off(this->p_->p_offset); } + { return Convert::convert_host(this->p_->p_offset); } typename Elf_types::Elf_Addr get_p_vaddr() const - { return internal::convert_addr(this->p_->p_vaddr); } + { return Convert::convert_host(this->p_->p_vaddr); } typename Elf_types::Elf_Addr get_p_paddr() const - { return internal::convert_addr(this->p_->p_paddr); } + { return Convert::convert_host(this->p_->p_paddr); } typename Elf_types::Elf_WXword get_p_filesz() const - { return internal::convert_wxword(this->p_->p_filesz); } + { return Convert::convert_host(this->p_->p_filesz); } typename Elf_types::Elf_WXword get_p_memsz() const - { return internal::convert_wxword(this->p_->p_memsz); } + { return Convert::convert_host(this->p_->p_memsz); } Elf_Word get_p_flags() const - { return internal::convert_word(this->p_->p_flags); } + { return Convert<32, big_endian>::convert_host(this->p_->p_flags); } typename Elf_types::Elf_WXword get_p_align() const - { return internal::convert_wxword(this->p_->p_align); } + { return Convert::convert_host(this->p_->p_align); } private: const internal::Phdr_data* p_; @@ -884,35 +867,35 @@ class Phdr_write void put_p_type(Elf_Word v) - { this->p_->p_type = internal::convert_word(v); } + { this->p_->p_type = Convert<32, big_endian>::convert_host(v); } void put_p_offset(typename Elf_types::Elf_Off v) - { this->p_->p_offset = internal::convert_off(v); } + { this->p_->p_offset = Convert::convert_host(v); } void put_p_vaddr(typename Elf_types::Elf_Addr v) - { this->p_->p_vaddr = internal::convert_addr(v); } + { this->p_->p_vaddr = Convert::convert_host(v); } void put_p_paddr(typename Elf_types::Elf_Addr v) - { this->p_->p_paddr = internal::convert_addr(v); } + { this->p_->p_paddr = Convert::convert_host(v); } void put_p_filesz(typename Elf_types::Elf_WXword v) - { this->p_->p_filesz = internal::convert_wxword(v); } + { this->p_->p_filesz = Convert::convert_host(v); } void put_p_memsz(typename Elf_types::Elf_WXword v) - { this->p_->p_memsz = internal::convert_wxword(v); } + { this->p_->p_memsz = Convert::convert_host(v); } void put_p_flags(Elf_Word v) - { this->p_->p_flags = internal::convert_word(v); } + { this->p_->p_flags = Convert<32, big_endian>::convert_host(v); } void put_p_align(typename Elf_types::Elf_WXword v) - { this->p_->p_align = internal::convert_wxword(v); } + { this->p_->p_align = Convert::convert_host(v); } private: internal::Phdr_data* p_; @@ -930,15 +913,15 @@ class Sym Elf_Word get_st_name() const - { return internal::convert_word(this->p_->st_name); } + { return Convert<32, big_endian>::convert_host(this->p_->st_name); } typename Elf_types::Elf_Addr get_st_value() const - { return internal::convert_addr(this->p_->st_value); } + { return Convert::convert_host(this->p_->st_value); } typename Elf_types::Elf_WXword get_st_size() const - { return internal::convert_wxword(this->p_->st_size); } + { return Convert::convert_host(this->p_->st_size); } unsigned char get_st_info() const @@ -966,7 +949,7 @@ class Sym Elf_Half get_st_shndx() const - { return internal::convert_half(this->p_->st_shndx); } + { return Convert<16, big_endian>::convert_host(this->p_->st_shndx); } private: const internal::Sym_data* p_; @@ -984,15 +967,15 @@ class Sym_write void put_st_name(Elf_Word v) - { this->p_->st_name = internal::convert_word(v); } + { this->p_->st_name = Convert<32, big_endian>::convert_host(v); } void put_st_value(typename Elf_types::Elf_Addr v) - { this->p_->st_value = internal::convert_addr(v); } + { this->p_->st_value = Convert::convert_host(v); } void put_st_size(typename Elf_types::Elf_WXword v) - { this->p_->st_size = internal::convert_wxword(v); } + { this->p_->st_size = Convert::convert_host(v); } void put_st_info(unsigned char v) @@ -1012,7 +995,7 @@ class Sym_write void put_st_shndx(Elf_Half v) - { this->p_->st_shndx = internal::convert_half(v); } + { this->p_->st_shndx = Convert<16, big_endian>::convert_host(v); } Sym sym() @@ -1034,11 +1017,11 @@ class Rel typename Elf_types::Elf_Addr get_r_offset() const - { return internal::convert_addr(this->p_->r_offset); } + { return Convert::convert_host(this->p_->r_offset); } typename Elf_types::Elf_WXword get_r_info() const - { return internal::convert_wxword(this->p_->r_info); } + { return Convert::convert_host(this->p_->r_info); } private: const internal::Rel_data* p_; @@ -1054,15 +1037,15 @@ class Rela typename Elf_types::Elf_Addr get_r_offset() const - { return internal::convert_addr(this->p_->r_offset); } + { return Convert::convert_host(this->p_->r_offset); } typename Elf_types::Elf_WXword get_r_info() const - { return internal::convert_wxword(this->p_->r_info); } + { return Convert::convert_host(this->p_->r_info); } typename Elf_types::Elf_Swxword get_r_addend() const - { return internal::convert_swxword(this->p_->r_addend); } + { return Convert::convert_host(this->p_->r_addend); } private: const internal::Rela_data* p_; diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h index e4c863644aa..c991535cb0a 100644 --- a/elfcpp/elfcpp_internal.h +++ b/elfcpp/elfcpp_internal.h @@ -5,8 +5,6 @@ #include "elfcpp_config.h" -#include - #ifndef ELFCPP_INTERNAL_H #define ELFCPP_INTERNAL_H @@ -16,163 +14,6 @@ namespace elfcpp namespace internal { -#ifdef WORDS_BIGENDIAN -const bool host_big_endian = true; -#else -const bool host_big_endian = false; -#endif - -// Conversion routines between target and host. - -// Convert Elf_Half. - -template -Elf_Half -convert_half_host(Elf_Half v); - -template<> -inline Elf_Half -convert_half_host(Elf_Half v) -{ - return v; -} - -template<> -inline Elf_Half -convert_half_host(Elf_Half v) -{ - return bswap_16(v); -} - -template -inline Elf_Half -convert_half(Elf_Half v) -{ - return convert_half_host(v); -} - -// Convert Elf_Word. - -template -Elf_Word -convert_word_host(Elf_Word v); - -template<> -inline Elf_Word -convert_word_host(Elf_Word v) -{ - return v; -} - -template<> -inline Elf_Word -convert_word_host(Elf_Word v) -{ - return bswap_32(v); -} - -template -inline Elf_Word -convert_word(Elf_Word v) -{ - return convert_word_host(v); -} - -// Convert Elf_Xword. - -template -Elf_Xword -convert_xword_host(Elf_Xword v); - -template<> -inline Elf_Xword -convert_xword_host(Elf_Xword v) -{ - return v; -} - -template<> -inline Elf_Xword -convert_xword_host(Elf_Xword v) -{ - return bswap_64(v); -} - -template -inline Elf_Xword -convert_xword(Elf_Xword v) -{ - return convert_xword_host(v); -} - -// Convert Elf_addr. - -template -typename Elf_types::Elf_Addr -convert_addr_size(typename Elf_types::Elf_Addr); - -template<> -inline Elf_types<32>::Elf_Addr -convert_addr_size<32, true>(Elf_types<32>::Elf_Addr v) -{ - return v; -} - -template<> -inline Elf_types<64>::Elf_Addr -convert_addr_size<64, true>(Elf_types<64>::Elf_Addr v) -{ - return v; -} - -template<> -inline Elf_types<32>::Elf_Addr -convert_addr_size<32, false>(Elf_types<32>::Elf_Addr v) -{ - return bswap_32(v); -} - -template<> -inline Elf_types<64>::Elf_Addr -convert_addr_size<64, false>(Elf_types<64>::Elf_Addr v) -{ - return bswap_64(v); -} - -template -inline typename Elf_types::Elf_Addr -convert_addr(typename Elf_types::Elf_Addr v) -{ - return convert_addr_size(v); -} - -// Convert Elf_Off. - -template -inline typename Elf_types::Elf_Off -convert_off(typename Elf_types::Elf_Off v) -{ - return convert_addr_size(v); -} - -// Convert Elf_WXword. - -template -inline typename Elf_types::Elf_WXword -convert_wxword(typename Elf_types::Elf_WXword v) -{ - return convert_addr_size(v); -} - -// Convert ELF_Swxword. - -template -inline typename Elf_types::Elf_Swxword -convert_swxword(typename Elf_types::Elf_Swxword v) -{ - return convert_addr_size(v); -} - // The ELF file header. template diff --git a/elfcpp/elfcpp_swap.h b/elfcpp/elfcpp_swap.h new file mode 100644 index 00000000000..979108e9e07 --- /dev/null +++ b/elfcpp/elfcpp_swap.h @@ -0,0 +1,350 @@ +// elfcpp_swap.h -- Handle swapping for elfcpp -*- C++ -*- + +// This header file defines basic template classes to efficiently swap +// numbers between host form and target form. When the host and +// target have the same endianness, these turn into no-ops. + +#ifndef ELFCPP_SWAP_H +#define ELFCPP_SWAP_H + +#include +#include +#include + +namespace elfcpp +{ + +// Endian simply indicates whether the host is big endian or not. + +struct Endian +{ + public: + // Used for template specializations. + static const bool host_big_endian = __BYTE_ORDER == __BIG_ENDIAN; +}; + +// Valtype_base is a template based on size (8, 16, 32, 64) which +// defines the type Valtype as the unsigned integer of the specified +// size. + +template +struct Valtype_base; + +template<> +struct Valtype_base<8> +{ + typedef unsigned char Valtype; +}; + +template<> +struct Valtype_base<16> +{ + typedef uint16_t Valtype; +}; + +template<> +struct Valtype_base<32> +{ + typedef uint32_t Valtype; +}; + +template<> +struct Valtype_base<64> +{ + typedef uint64_t Valtype; +}; + +// Convert_endian is a template based on size and on whether the host +// and target have the same endianness. It defines the type Valtype +// as Valtype_base does, and also defines a function convert_host +// which takes an argument of type Valtype and returns the same value, +// but swapped if the host and target have different endianness. + +template +struct Convert_endian; + +template +struct Convert_endian +{ + typedef typename Valtype_base::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { return v; } +}; + +template<> +struct Convert_endian<8, false> +{ + typedef Valtype_base<8>::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { return v; } +}; + +template<> +struct Convert_endian<16, false> +{ + typedef Valtype_base<16>::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { return bswap_16(v); } +}; + +template<> +struct Convert_endian<32, false> +{ + typedef Valtype_base<32>::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { return bswap_32(v); } +}; + +template<> +struct Convert_endian<64, false> +{ + typedef Valtype_base<64>::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { return bswap_64(v); } +}; + +// Convert is a template based on size and on whether the target is +// big endian. It defines Valtype and convert_host like +// Convert_endian. That is, it is just like Convert_endian except in +// the meaning of the second template parameter. + +template +struct Convert +{ + typedef typename Valtype_base::Valtype Valtype; + + static inline Valtype + convert_host(Valtype v) + { + return Convert_endian + ::convert_host(v); + } +}; + +// Swap is a template based on size and on whether the target is big +// endian. It defines the type Valtype and the functions readval and +// writeval. The functions read and write values of the appropriate +// size out of buffers, swapping them if necessary. readval and +// writeval are overloaded to take pointers to the appropriate type or +// pointers to unsigned char. + +template +struct Swap +{ + typedef typename Valtype_base::Valtype Valtype; + + static inline Valtype + readval(const Valtype* wv) + { return Convert::convert_host(*wv); } + + static inline void + writeval(Valtype* wv, Valtype v) + { *wv = Convert::convert_host(v); } + + static inline Valtype + readval(const unsigned char* wv) + { return readval(reinterpret_cast(wv)); } + + static inline void + writeval(unsigned char* wv, Valtype v) + { writeval(reinterpret_cast(wv), v); } +}; + +// We need to specialize the 8-bit version of Swap to avoid +// conflicting overloads, since both versions of readval and writeval +// will have the same type parameters. + +template +struct Swap<8, big_endian> +{ + typedef typename Valtype_base<8>::Valtype Valtype; + + static inline Valtype + readval(const Valtype* wv) + { return *wv; } + + static inline void + writeval(Valtype* wv, Valtype v) + { *wv = v; } +}; + +// Swap_unaligned is a template based on size and on whether the +// target is big endian. It defines the type Valtype and the +// functions readval_unaligned and writeval_unaligned. The functions +// read and write values of the appropriate size out of buffers which +// may be misaligned. + +template +struct Swap_unaligned; + +template +struct Swap_unaligned<8, big_endian> +{ + typedef typename Valtype_base<8>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { return *wv; } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { *wv = v; } +}; + +template<> +struct Swap_unaligned<16, false> +{ + typedef Valtype_base<16>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return (wv[1] << 8) | wv[0]; + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[1] = v >> 8; + wv[0] = v; + } +}; + +template<> +struct Swap_unaligned<16, true> +{ + typedef Valtype_base<16>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return (wv[0] << 8) | wv[1]; + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[0] = v >> 8; + wv[1] = v; + } +}; + +template<> +struct Swap_unaligned<32, false> +{ + typedef Valtype_base<32>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return (wv[3] << 24) | (wv[2] << 16) | (wv[1] << 8) | wv[0]; + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[3] = v >> 24; + wv[2] = v >> 16; + wv[1] = v >> 8; + wv[0] = v; + } +}; + +template<> +struct Swap_unaligned<32, true> +{ + typedef Valtype_base<32>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return (wv[0] << 24) | (wv[1] << 16) | (wv[2] << 8) | wv[3]; + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[0] = v >> 24; + wv[1] = v >> 16; + wv[2] = v >> 8; + wv[3] = v; + } +}; + +template<> +struct Swap_unaligned<64, false> +{ + typedef Valtype_base<64>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return ((static_cast(wv[7]) << 56) + | (static_cast(wv[6]) << 48) + | (static_cast(wv[5]) << 40) + | (static_cast(wv[4]) << 32) + | (static_cast(wv[3]) << 24) + | (static_cast(wv[2]) << 16) + | (static_cast(wv[1]) << 8) + | static_cast(wv[0])); + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[7] = v >> 56; + wv[6] = v >> 48; + wv[5] = v >> 40; + wv[4] = v >> 32; + wv[3] = v >> 24; + wv[2] = v >> 16; + wv[1] = v >> 8; + wv[0] = v; + } +}; + +template<> +struct Swap_unaligned<64, true> +{ + typedef Valtype_base<64>::Valtype Valtype; + + static inline Valtype + readval_unaligned(const unsigned char* wv) + { + return ((static_cast(wv[0]) << 56) + | (static_cast(wv[1]) << 48) + | (static_cast(wv[2]) << 40) + | (static_cast(wv[3]) << 32) + | (static_cast(wv[4]) << 24) + | (static_cast(wv[5]) << 16) + | (static_cast(wv[6]) << 8) + | static_cast(wv[7])); + } + + static inline void + writeval_unaligned(unsigned char* wv, Valtype v) + { + wv[7] = v >> 56; + wv[6] = v >> 48; + wv[5] = v >> 40; + wv[4] = v >> 32; + wv[3] = v >> 24; + wv[2] = v >> 16; + wv[1] = v >> 8; + wv[0] = v; + } +}; + +} // End namespace elfcpp. + +#endif // !defined(ELFCPP_SWAP_H) -- 2.30.2