diff options
author | Ian Lance Taylor <iant@google.com> | 2006-09-29 19:58:17 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-09-29 19:58:17 +0000 |
commit | 61ba1cf93601b0a0877a8ade94ba3c674a09f77e (patch) | |
tree | ffa744ec1dffd7f2dae13150b1dd7784728ed0a4 /elfcpp | |
parent | 4dba4b2419ccdbf48fd016edb7e0e10016897827 (diff) | |
download | gdb-61ba1cf93601b0a0877a8ade94ba3c674a09f77e.zip gdb-61ba1cf93601b0a0877a8ade94ba3c674a09f77e.tar.gz gdb-61ba1cf93601b0a0877a8ade94ba3c674a09f77e.tar.bz2 |
Snapshot. Now able to produce a minimal executable which actually
runs.
Diffstat (limited to 'elfcpp')
-rw-r--r-- | elfcpp/elfcpp.h | 288 | ||||
-rw-r--r-- | elfcpp/elfcpp_internal.h | 30 | ||||
-rw-r--r-- | elfcpp/i386.h | 63 |
3 files changed, 379 insertions, 2 deletions
diff --git a/elfcpp/elfcpp.h b/elfcpp/elfcpp.h index 6f8f0dd..3ae005d 100644 --- a/elfcpp/elfcpp.h +++ b/elfcpp/elfcpp.h @@ -34,6 +34,7 @@ struct Elf_types<32> typedef uint32_t Elf_Addr; typedef uint32_t Elf_Off; typedef uint32_t Elf_WXword; + typedef int32_t Elf_Swxword; }; template<> @@ -42,6 +43,7 @@ struct Elf_types<64> typedef uint64_t Elf_Addr; typedef uint64_t Elf_Off; typedef uint64_t Elf_WXword; + typedef int64_t Elf_Swxword; }; // Offsets within the Ehdr e_ident field. @@ -471,6 +473,62 @@ elf_st_other(STV vis, unsigned char nonvis) + (static_cast<unsigned char>(vis) & 3)); } +// Reloc information from Rel/Rela r_info field. + +template<int size> +unsigned int +elf_r_sym(typename Elf_types<size>::Elf_WXword); + +template<> +inline unsigned int +elf_r_sym<32>(Elf_Word v) +{ + return v >> 8; +} + +template<> +inline unsigned int +elf_r_sym<64>(Elf_Xword v) +{ + return v >> 32; +} + +template<int size> +unsigned int +elf_r_type(typename Elf_types<size>::Elf_WXword); + +template<> +inline unsigned int +elf_r_type<32>(Elf_Word v) +{ + return v & 0xff; +} + +template<> +inline unsigned int +elf_r_type<64>(Elf_Xword v) +{ + return v & 0xffffffff; +} + +template<int size> +typename Elf_types<size>::Elf_WXword +elf_r_info(unsigned int s, unsigned int t); + +template<> +inline Elf_Word +elf_r_info<32>(unsigned int s, unsigned int t) +{ + return (s << 8) + (t & 0xff); +} + +template<> +inline Elf_Xword +elf_r_info<64>(unsigned int s, unsigned int t) +{ + return (static_cast<Elf_Xword>(s) << 32) + (t & 0xffffffff); +} + } // End namespace elfcpp. // Include internal details after defining the types. @@ -490,10 +548,15 @@ struct Elf_sizes { // Size of ELF file header. static const int ehdr_size = sizeof(internal::Ehdr_data<size>); + // Size of ELF segment header. + static const int phdr_size = sizeof(internal::Phdr_data<size>); // Size of ELF section header. static const int shdr_size = sizeof(internal::Shdr_data<size>); // Size of ELF symbol table entry. static const int sym_size = sizeof(internal::Sym_data<size>); + // Sizes of ELF reloc entries. + static const int rel_size = sizeof(internal::Rel_data<size>); + static const int rela_size = sizeof(internal::Rela_data<size>); }; // Given the address of an Elf_Word, return the value. @@ -505,6 +568,15 @@ read_elf_word(const Elf_Word* p) return internal::convert_word<big_endian>(*p); } +// Store an Elf_Word into an address. + +template<bool big_endian> +inline void +write_elf_word(Elf_Word* p, Elf_Word v) +{ + *p = internal::convert_word<big_endian>(v); +} + // Accessor class for the ELF file header. template<int size, bool big_endian> @@ -575,6 +647,76 @@ class Ehdr const internal::Ehdr_data<size>* p_; }; +// Write class for the ELF file header. + +template<int size, bool big_endian> +class Ehdr_write +{ + public: + Ehdr_write(unsigned char* p) + : p_(reinterpret_cast<internal::Ehdr_data<size>*>(p)) + { } + + void + put_e_ident(const unsigned char v[EI_NIDENT]) const + { memcpy(this->p_->e_ident, v, EI_NIDENT); } + + void + put_e_type(Elf_Half v) + { this->p_->e_type = internal::convert_half<big_endian>(v); } + + void + put_e_machine(Elf_Half v) + { this->p_->e_machine = internal::convert_half<big_endian>(v); } + + void + put_e_version(Elf_Word v) + { this->p_->e_version = internal::convert_word<big_endian>(v); } + + void + put_e_entry(typename Elf_types<size>::Elf_Addr v) + { this->p_->e_entry = internal::convert_addr<size, big_endian>(v); } + + void + put_e_phoff(typename Elf_types<size>::Elf_Off v) + { this->p_->e_phoff = internal::convert_off<size, big_endian>(v); } + + void + put_e_shoff(typename Elf_types<size>::Elf_Off v) + { this->p_->e_shoff = internal::convert_off<size, big_endian>(v); } + + void + put_e_flags(Elf_Word v) + { this->p_->e_flags = internal::convert_word<big_endian>(v); } + + void + put_e_ehsize(Elf_Half v) + { this->p_->e_ehsize = internal::convert_half<big_endian>(v); } + + void + put_e_phentsize(Elf_Half v) + { this->p_->e_phentsize = internal::convert_half<big_endian>(v); } + + void + put_e_phnum(Elf_Half v) + { this->p_->e_phnum = internal::convert_half<big_endian>(v); } + + void + put_e_shentsize(Elf_Half v) + { this->p_->e_shentsize = internal::convert_half<big_endian>(v); } + + void + put_e_shnum(Elf_Half v) + { this->p_->e_shnum = internal::convert_half<big_endian>(v); } + + void + put_e_shstrndx(Elf_Half v) + { this->p_->e_shstrndx = internal::convert_half<big_endian>(v); } + + private: + internal::Ehdr_data<size>* p_; +}; + // Accessor class for an ELF section header. template<int size, bool big_endian> @@ -630,6 +772,60 @@ class Shdr const internal::Shdr_data<size>* p_; }; +// Write class for an ELF section header. + +template<int size, bool big_endian> +class Shdr_write +{ + public: + Shdr_write(unsigned char* p) + : p_(reinterpret_cast<internal::Shdr_data<size>*>(p)) + { } + + void + put_sh_name(Elf_Word v) + { this->p_->sh_name = internal::convert_word<big_endian>(v); } + + void + put_sh_type(Elf_Word v) + { this->p_->sh_type = internal::convert_word<big_endian>(v); } + + void + put_sh_flags(typename Elf_types<size>::Elf_WXword v) + { this->p_->sh_flags = internal::convert_wxword<size, big_endian>(v); } + + void + put_sh_addr(typename Elf_types<size>::Elf_Addr v) + { this->p_->sh_addr = internal::convert_addr<size, big_endian>(v); } + + void + put_sh_offset(typename Elf_types<size>::Elf_Off v) + { this->p_->sh_offset = internal::convert_off<size, big_endian>(v); } + + void + put_sh_size(typename Elf_types<size>::Elf_WXword v) + { this->p_->sh_size = internal::convert_wxword<size, big_endian>(v); } + + void + put_sh_link(Elf_Word v) + { this->p_->sh_link = internal::convert_word<big_endian>(v); } + + void + put_sh_info(Elf_Word v) + { this->p_->sh_info = internal::convert_word<big_endian>(v); } + + void + put_sh_addralign(typename Elf_types<size>::Elf_WXword v) + { this->p_->sh_addralign = internal::convert_wxword<size, big_endian>(v); } + + void + put_sh_entsize(typename Elf_types<size>::Elf_WXword v) + { this->p_->sh_entsize = internal::convert_wxword<size, big_endian>(v); } + + private: + internal::Shdr_data<size>* p_; +}; + // Accessor class for an ELF segment header. template<int size, bool big_endian> @@ -676,6 +872,52 @@ class Phdr const internal::Phdr_data<size>* p_; }; +// Write class for an ELF segment header. + +template<int size, bool big_endian> +class Phdr_write +{ + public: + Phdr_write(unsigned char* p) + : p_(reinterpret_cast<internal::Phdr_data<size>*>(p)) + { } + + void + put_p_type(Elf_Word v) + { this->p_->p_type = internal::convert_word<big_endian>(v); } + + void + put_p_offset(typename Elf_types<size>::Elf_Off v) + { this->p_->p_offset = internal::convert_off<size, big_endian>(v); } + + void + put_p_vaddr(typename Elf_types<size>::Elf_Addr v) + { this->p_->p_vaddr = internal::convert_addr<size, big_endian>(v); } + + void + put_p_paddr(typename Elf_types<size>::Elf_Addr v) + { this->p_->p_paddr = internal::convert_addr<size, big_endian>(v); } + + void + put_p_filesz(typename Elf_types<size>::Elf_WXword v) + { this->p_->p_filesz = internal::convert_wxword<size, big_endian>(v); } + + void + put_p_memsz(typename Elf_types<size>::Elf_WXword v) + { this->p_->p_memsz = internal::convert_wxword<size, big_endian>(v); } + + void + put_p_flags(Elf_Word v) + { this->p_->p_flags = internal::convert_word<big_endian>(v); } + + void + put_p_align(typename Elf_types<size>::Elf_WXword v) + { this->p_->p_align = internal::convert_wxword<size, big_endian>(v); } + + private: + internal::Phdr_data<size>* p_; +}; + // Accessor class for an ELF symbol table entry. template<int size, bool big_endian> @@ -780,6 +1022,52 @@ class Sym_write internal::Sym_data<size>* p_; }; +// Accessor classes for Elf relocation table entries. + +template<int size, bool big_endian> +class Rel +{ + public: + Rel(const unsigned char* p) + : p_(reinterpret_cast<const internal::Rel_data<size>*>(p)) + { } + + typename Elf_types<size>::Elf_Addr + get_r_offset() const + { return internal::convert_addr<size, big_endian>(this->p_->r_offset); } + + typename Elf_types<size>::Elf_WXword + get_r_info() const + { return internal::convert_wxword<size, big_endian>(this->p_->r_info); } + + private: + const internal::Rel_data<size>* p_; +}; + +template<int size, bool big_endian> +class Rela +{ + public: + Rela(const unsigned char* p) + : p_(reinterpret_cast<const internal::Rela_data<size>*>(p)) + { } + + typename Elf_types<size>::Elf_Addr + get_r_offset() const + { return internal::convert_addr<size, big_endian>(this->p_->r_offset); } + + typename Elf_types<size>::Elf_WXword + get_r_info() const + { return internal::convert_wxword<size, big_endian>(this->p_->r_info); } + + typename Elf_types<size>::Elf_Swxword + get_r_addend() const + { return internal::convert_swxword<size, big_endian>(this->p_->r_addend); } + + private: + const internal::Rela_data<size>* p_; +}; + } // End namespace elfcpp. #endif // !defined(ELFPCP_H) diff --git a/elfcpp/elfcpp_internal.h b/elfcpp/elfcpp_internal.h index 696343a..0d69bae 100644 --- a/elfcpp/elfcpp_internal.h +++ b/elfcpp/elfcpp_internal.h @@ -158,8 +158,17 @@ convert_off(typename Elf_types<size>::Elf_Off v) // Convert Elf_WXword. template<int size, bool big_endian> -inline typename Elf_types<size>::Elf_Off -convert_wxword(typename Elf_types<size>::Elf_Off v) +inline typename Elf_types<size>::Elf_WXword +convert_wxword(typename Elf_types<size>::Elf_WXword v) +{ + return convert_addr_size<size, big_endian == host_big_endian>(v); +} + +// Convert ELF_Swxword. + +template<int size, bool big_endian> +inline typename Elf_types<size>::Elf_Swxword +convert_swxword(typename Elf_types<size>::Elf_Swxword v) { return convert_addr_size<size, big_endian == host_big_endian>(v); } @@ -264,6 +273,23 @@ struct Sym_data<64> Elf_Xword st_size; }; +// Elf relocation table entries. + +template<int size> +struct Rel_data +{ + typename Elf_types<size>::Elf_Addr r_offset; + typename Elf_types<size>::Elf_WXword r_info; +}; + +template<int size> +struct Rela_data +{ + typename Elf_types<size>::Elf_Addr r_offset; + typename Elf_types<size>::Elf_WXword r_info; + typename Elf_types<size>::Elf_Swxword r_addend; +}; + } // End namespace internal. } // End namespace elfcpp. diff --git a/elfcpp/i386.h b/elfcpp/i386.h new file mode 100644 index 0000000..01efd87 --- /dev/null +++ b/elfcpp/i386.h @@ -0,0 +1,63 @@ +// i386.h -- ELF definitions specific to EM_386 -*- C++ -*- + +#ifndef ELFCPP_I386_H +#define ELFCPP_I386_H + +namespace elfcpp +{ + +enum +{ + R_386_NONE = 0, + R_386_32 = 1, + R_386_PC32 = 2, + R_386_GOT32 = 3, + R_386_PLT32 = 4, + R_386_COPY = 5, + R_386_GLOB_DAT = 6, + R_386_JUMP_SLOT = 7, + R_386_RELATIVE = 8, + R_386_GOTOFF = 9, + R_386_GOTPC = 10, + // Used by Sun. + R_386_32PLT = 11, + // TLS extensions. + R_386_TLS_TPOFF = 14, + R_386_TLS_IE = 15, + R_386_TLS_GOTIE = 16, + R_386_TLS_LE = 17, + R_386_TLS_GD = 18, + R_386_TLS_LDM = 19, + // GNU extensions. + R_386_16 = 20, + R_386_PC16 = 21, + R_386_8 = 22, + R_386_PC8 = 23, + // More TLS relocs. + R_386_TLS_GD_32 = 24, + R_386_TLS_GD_PUSH = 25, + R_386_TLS_GD_CALL = 26, + R_386_TLS_GD_POP = 27, + R_386_TLS_LDM_32 = 28, + R_386_TLS_LDM_PUSH = 29, + R_386_TLS_LDM_CALL = 30, + R_386_TLS_LDM_POP = 31, + R_386_TLS_LDO_32 = 32, + R_386_TLS_IE_32 = 33, + R_386_TLS_LE_32 = 34, + R_386_TLS_DTPMOD32 = 35, + R_386_TLS_DTPOFF32 = 36, + R_386_TLS_TPOFF32 = 37, + R_386_TLS_GOTDESC = 39, + R_386_TLS_DESC_CALL = 40, + R_386_TLS_DESC = 41, + // Used by Intel. + R_386_USED_BY_INTEL_200 = 200, + // GNU vtable garbage collection extensions. + R_386_GNU_VTINHERIT = 250, + R_386_GNU_VTENTRY = 251 +}; + +} // End namespace elfcpp. + +#endif // !defined(ELFCPP_I386_H) |