diff options
Diffstat (limited to 'trunk/src/reloc-info.c')
-rw-r--r-- | trunk/src/reloc-info.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/trunk/src/reloc-info.c b/trunk/src/reloc-info.c new file mode 100644 index 0000000..4ce333c --- /dev/null +++ b/trunk/src/reloc-info.c @@ -0,0 +1,215 @@ +/* Copyright (C) 2008 CodeSourcery + Written by Maciej W. Rozycki <macro@codesourcery.com>, 2008. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> + +#include "prelink.h" +#include "reloc-info.h" + +/* A structure to lay out generic relocation information + * in a way specific to 64-bit MIPS. */ +union mips64_r_info +{ + /* Generic r_info interpretation. */ + Elf64_Xword r_info; + + /* 64-bit MIPS r_info interpretation. */ + struct + { + /* Symbol index for the first relocation. */ + Elf64_Word r_sym; + + /* Special symbol for the second relocation. */ + Elf64_Byte r_ssym; + + /* Third relocation. */ + Elf64_Byte r_type3; + + /* Second relocation. */ + Elf64_Byte r_type2; + + /* First relocation. */ + Elf64_Byte r_type; + } + s_info; +}; + +/* Extract the symbol index from 64-bit MIPS reloc info. */ + +static GElf_Xword +mips64_r_sym (DSO *dso, GElf_Xword r_info) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info); + return buf_read_une32 (dso, (unsigned char *) &mips64_r_info.s_info.r_sym); +} + +/* Extract the special symbol index from 64-bit MIPS reloc info. */ + +static GElf_Xword +mips64_r_ssym (DSO *dso, GElf_Xword r_info) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info); + return mips64_r_info.s_info.r_ssym; +} + +/* Extract the first reloc type from 64-bit MIPS reloc info. */ + +static GElf_Xword +mips64_r_type (DSO *dso, GElf_Xword r_info) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info); + return mips64_r_info.s_info.r_type; +} + +/* Extract the second reloc type from 64-bit MIPS reloc info. */ + +static GElf_Xword +mips64_r_type2 (DSO *dso, GElf_Xword r_info) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info); + return mips64_r_info.s_info.r_type2; +} + +/* Extract the third reloc type from 64-bit MIPS reloc info. */ + +static GElf_Xword +mips64_r_type3 (DSO *dso, GElf_Xword r_info) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne64 (dso, (unsigned char *) &mips64_r_info.r_info, r_info); + return mips64_r_info.s_info.r_type3; +} + +/* Construct 64-bit MIPS reloc info from symbol indices and reloc types. */ + +static GElf_Xword +mips64_r_info_ext (DSO *dso, GElf_Word r_sym, Elf64_Byte r_ssym, + Elf64_Byte r_type, Elf64_Byte r_type2, Elf64_Byte r_type3) +{ + union mips64_r_info mips64_r_info; + + buf_write_ne32 (dso, (unsigned char *) &mips64_r_info.s_info.r_sym, r_sym); + mips64_r_info.s_info.r_ssym = r_ssym; + mips64_r_info.s_info.r_type = r_type; + mips64_r_info.s_info.r_type2 = r_type2; + mips64_r_info.s_info.r_type3 = r_type3; + return buf_read_une64 (dso, (unsigned char *) &mips64_r_info.r_info); +} + + +/* Extract the symbol index from reloc info. */ + +GElf_Xword +reloc_r_sym (DSO *dso, GElf_Xword r_info) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_sym (dso, r_info); + else + return GELF_R_SYM (r_info); +} + +/* Extract the special symbol index from reloc info. */ + +GElf_Xword +reloc_r_ssym (DSO *dso, GElf_Xword r_info) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_ssym (dso, r_info); + else + return RSS_UNDEF; +} + +/* Extract the first reloc type from reloc info. */ + +GElf_Xword +reloc_r_type (DSO *dso, GElf_Xword r_info) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_type (dso, r_info); + else + return GELF_R_TYPE (r_info); +} + +/* Extract the second reloc type from reloc info. */ + +GElf_Xword +reloc_r_type2 (DSO *dso, GElf_Xword r_info) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_type2 (dso, r_info); + else + return 0; +} + +/* Extract the third reloc type from reloc info. */ + +GElf_Xword +reloc_r_type3 (DSO *dso, GElf_Xword r_info) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_type3 (dso, r_info); + else + return 0; +} + +/* Construct reloc info from symbol index and reloc type. */ + +GElf_Xword +reloc_r_info (DSO *dso, GElf_Word r_sym, GElf_Word r_type) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + switch (r_type) + { + case R_MIPS_REL32: + case R_MIPS_GLOB_DAT: + return mips64_r_info_ext (dso, r_sym, RSS_UNDEF, + r_type, R_MIPS_64, R_MIPS_NONE); + default: + return mips64_r_info_ext (dso, r_sym, RSS_UNDEF, + r_type, R_MIPS_NONE, R_MIPS_NONE); + } + else + return GELF_R_INFO (r_sym, r_type); +} + +/* Construct reloc info from symbol index and reloc type. */ + +GElf_Xword +reloc_r_info_ext (DSO *dso, GElf_Word r_sym, Elf64_Byte r_ssym, + Elf64_Byte r_type, Elf64_Byte r_type2, Elf64_Byte r_type3) +{ + if (dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 + && dso->ehdr.e_machine == EM_MIPS) + return mips64_r_info_ext (dso, r_sym, r_ssym, r_type, r_type2, r_type3); + else + return GELF_R_INFO (r_sym, r_type); +} |