📄 elf32-mips.c
字号:
/* MIPS-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Most of the information added by Ian Lance Taylor, Cygnus Support, <ian@cygnus.com>. N32/64 ABI support added by Mark Mitchell, CodeSourcery, LLC. <mark@codesourcery.com> Traditional MIPS targets support added by Koundinya.K, Dansk Data Elektronik & Operations Research Group. <kk@ddeorg.soft.net>This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *//* This file handles MIPS ELF targets. SGI Irix 5 uses a slightly different MIPS ELF from other targets. This matters when linking. This file supports both, switching at runtime. */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "bfdlink.h"#include "genlink.h"#include "elf-bfd.h"#include "elf/mips.h"/* Get the ECOFF swapping routines. */#include "coff/sym.h"#include "coff/symconst.h"#include "coff/internal.h"#include "coff/ecoff.h"#include "coff/mips.h"#define ECOFF_SIGNED_32#include "ecoffswap.h"/* This structure is used to hold .got information when linking. It is stored in the tdata field of the bfd_elf_section_data structure. */struct mips_got_info{ /* The global symbol in the GOT with the lowest index in the dynamic symbol table. */ struct elf_link_hash_entry *global_gotsym; /* The number of global .got entries. */ unsigned int global_gotno; /* The number of local .got entries. */ unsigned int local_gotno; /* The number of local .got entries we have used. */ unsigned int assigned_gotno;};/* The MIPS ELF linker needs additional information for each symbol in the global hash table. */struct mips_elf_link_hash_entry{ struct elf_link_hash_entry root; /* External symbol information. */ EXTR esym; /* Number of R_MIPS_32, R_MIPS_REL32, or R_MIPS_64 relocs against this symbol. */ unsigned int possibly_dynamic_relocs; /* The index of the first dynamic relocation (in the .rel.dyn section) against this symbol. */ unsigned int min_dyn_reloc_index; /* We must not create a stub for a symbol that has relocations related to taking the function's address, i.e. any but R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition", p. 4-20. */ boolean no_fn_stub; /* If there is a stub that 32 bit functions should use to call this 16 bit function, this points to the section containing the stub. */ asection *fn_stub; /* Whether we need the fn_stub; this is set if this symbol appears in any relocs other than a 16 bit call. */ boolean need_fn_stub; /* If there is a stub that 16 bit functions should use to call this 32 bit function, this points to the section containing the stub. */ asection *call_stub; /* This is like the call_stub field, but it is used if the function being called returns a floating point value. */ asection *call_fp_stub;};static bfd_reloc_status_type mips32_64bit_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));static reloc_howto_type *mips_rtype_to_howto PARAMS ((unsigned int));static void mips_info_to_howto_rel PARAMS ((bfd *, arelent *, Elf32_Internal_Rel *));static void mips_info_to_howto_rela PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));static void bfd_mips_elf32_swap_gptab_in PARAMS ((bfd *, const Elf32_External_gptab *, Elf32_gptab *));static void bfd_mips_elf32_swap_gptab_out PARAMS ((bfd *, const Elf32_gptab *, Elf32_External_gptab *));#if 0static void bfd_mips_elf_swap_msym_in PARAMS ((bfd *, const Elf32_External_Msym *, Elf32_Internal_Msym *));#endifstatic void bfd_mips_elf_swap_msym_out PARAMS ((bfd *, const Elf32_Internal_Msym *, Elf32_External_Msym *));static boolean mips_elf_sym_is_global PARAMS ((bfd *, asymbol *));static boolean mips_elf_create_procedure_table PARAMS ((PTR, bfd *, struct bfd_link_info *, asection *, struct ecoff_debug_info *));static INLINE int elf_mips_isa PARAMS ((flagword));static INLINE int elf_mips_mach PARAMS ((flagword));static INLINE char* elf_mips_abi_name PARAMS ((bfd *));static boolean mips_elf_is_local_label_name PARAMS ((bfd *, const char *));static struct bfd_hash_entry *mips_elf_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static int gptab_compare PARAMS ((const void *, const void *));static bfd_reloc_status_type mips16_jump_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type mips16_gprel_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static boolean mips_elf_create_compact_rel_section PARAMS ((bfd *, struct bfd_link_info *));static boolean mips_elf_create_got_section PARAMS ((bfd *, struct bfd_link_info *));static bfd_reloc_status_type mips_elf_final_gp PARAMS ((bfd *, asymbol *, boolean, char **, bfd_vma *));static bfd_byte *elf32_mips_get_relocated_section_contents PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, bfd_byte *, boolean, asymbol **));static asection *mips_elf_create_msym_section PARAMS ((bfd *));static void mips_elf_irix6_finish_dynamic_symbol PARAMS ((bfd *, const char *, Elf_Internal_Sym *));static bfd_vma mips_elf_sign_extend PARAMS ((bfd_vma, int));static boolean mips_elf_overflow_p PARAMS ((bfd_vma, int));static bfd_vma mips_elf_high PARAMS ((bfd_vma));static bfd_vma mips_elf_higher PARAMS ((bfd_vma));static bfd_vma mips_elf_highest PARAMS ((bfd_vma));static bfd_vma mips_elf_global_got_index PARAMS ((bfd *, struct elf_link_hash_entry *));static bfd_vma mips_elf_local_got_index PARAMS ((bfd *, struct bfd_link_info *, bfd_vma));static bfd_vma mips_elf_got_offset_from_index PARAMS ((bfd *, bfd *, bfd_vma));static boolean mips_elf_record_global_got_symbol PARAMS ((struct elf_link_hash_entry *, struct bfd_link_info *, struct mips_got_info *));static bfd_vma mips_elf_got_page PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, bfd_vma *));static const Elf_Internal_Rela *mips_elf_next_relocation PARAMS ((unsigned int, const Elf_Internal_Rela *, const Elf_Internal_Rela *));static bfd_reloc_status_type mips_elf_calculate_relocation PARAMS ((bfd *, bfd *, asection *, struct bfd_link_info *, const Elf_Internal_Rela *, bfd_vma, reloc_howto_type *, Elf_Internal_Sym *, asection **, bfd_vma *, const char **, boolean *));static bfd_vma mips_elf_obtain_contents PARAMS ((reloc_howto_type *, const Elf_Internal_Rela *, bfd *, bfd_byte *));static boolean mips_elf_perform_relocation PARAMS ((struct bfd_link_info *, reloc_howto_type *, const Elf_Internal_Rela *, bfd_vma, bfd *, asection *, bfd_byte *, boolean));static boolean mips_elf_assign_gp PARAMS ((bfd *, bfd_vma *));static boolean mips_elf_sort_hash_table_f PARAMS ((struct mips_elf_link_hash_entry *, PTR));static boolean mips_elf_sort_hash_table PARAMS ((struct bfd_link_info *, unsigned long));static asection * mips_elf_got_section PARAMS ((bfd *));static struct mips_got_info *mips_elf_got_info PARAMS ((bfd *, asection **));static boolean mips_elf_local_relocation_p PARAMS ((bfd *, const Elf_Internal_Rela *, asection **, boolean));static bfd_vma mips_elf_create_local_got_entry PARAMS ((bfd *, struct mips_got_info *, asection *, bfd_vma));static bfd_vma mips_elf_got16_entry PARAMS ((bfd *, struct bfd_link_info *, bfd_vma, boolean));static boolean mips_elf_create_dynamic_relocation PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *, struct mips_elf_link_hash_entry *, asection *, bfd_vma, bfd_vma *, asection *));static void mips_elf_allocate_dynamic_relocations PARAMS ((bfd *, unsigned int));static boolean mips_elf_stub_section_p PARAMS ((bfd *, asection *));static int sort_dynamic_relocs PARAMS ((const void *, const void *));extern const bfd_target bfd_elf32_tradbigmips_vec;extern const bfd_target bfd_elf32_tradlittlemips_vec;#ifdef BFD64extern const bfd_target bfd_elf64_tradbigmips_vec;extern const bfd_target bfd_elf64_tradlittlemips_vec;#endif/* The level of IRIX compatibility we're striving for. */typedef enum { ict_none, ict_irix5, ict_irix6} irix_compat_t;/* This will be used when we sort the dynamic relocation records. */static bfd *reldyn_sorting_bfd;/* Nonzero if ABFD is using the N32 ABI. */#define ABI_N32_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_ABI2) != 0)/* Nonzero if ABFD is using the 64-bit ABI. */#define ABI_64_P(abfd) \ ((elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) != 0)/* Depending on the target vector we generate some version of Irix executables or "normal" MIPS ELF ABI executables. */#ifdef BFD64#define IRIX_COMPAT(abfd) \ (((abfd->xvec == &bfd_elf64_tradbigmips_vec) || \ (abfd->xvec == &bfd_elf64_tradlittlemips_vec) || \ (abfd->xvec == &bfd_elf32_tradbigmips_vec) || \ (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \ ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))#else#define IRIX_COMPAT(abfd) \ (((abfd->xvec == &bfd_elf32_tradbigmips_vec) || \ (abfd->xvec == &bfd_elf32_tradlittlemips_vec)) ? ict_none : \ ((ABI_N32_P (abfd) || ABI_64_P (abfd)) ? ict_irix6 : ict_irix5))#endif/* Whether we are trying to be compatible with IRIX at all. */#define SGI_COMPAT(abfd) \ (IRIX_COMPAT (abfd) != ict_none)/* The name of the msym section. */#define MIPS_ELF_MSYM_SECTION_NAME(abfd) ".msym"/* The name of the srdata section. */#define MIPS_ELF_SRDATA_SECTION_NAME(abfd) ".srdata"/* The name of the options section. */#define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \ (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.options" : ".options")/* The name of the stub section. */#define MIPS_ELF_STUB_SECTION_NAME(abfd) \ (IRIX_COMPAT (abfd) == ict_irix6 ? ".MIPS.stubs" : ".stub")/* The name of the dynamic relocation section. */#define MIPS_ELF_REL_DYN_SECTION_NAME(abfd) ".rel.dyn"/* The size of an external REL relocation. */#define MIPS_ELF_REL_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_rel)/* The size of an external dynamic table entry. */#define MIPS_ELF_DYN_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_dyn)/* The size of a GOT entry. */#define MIPS_ELF_GOT_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->arch_size / 8)/* The size of a symbol-table entry. */#define MIPS_ELF_SYM_SIZE(abfd) \ (get_elf_backend_data (abfd)->s->sizeof_sym)/* The default alignment for sections, as a power of two. */#define MIPS_ELF_LOG_FILE_ALIGN(abfd) \ (get_elf_backend_data (abfd)->s->file_align == 8 ? 3 : 2)/* Get word-sized data. */#define MIPS_ELF_GET_WORD(abfd, ptr) \ (ABI_64_P (abfd) ? bfd_get_64 (abfd, ptr) : bfd_get_32 (abfd, ptr))/* Put out word-sized data. */#define MIPS_ELF_PUT_WORD(abfd, val, ptr) \ (ABI_64_P (abfd) \ ? bfd_put_64 (abfd, val, ptr) \ : bfd_put_32 (abfd, val, ptr))/* Add a dynamic symbol table-entry. */#ifdef BFD64#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \ (ABI_64_P (elf_hash_table (info)->dynobj) \ ? bfd_elf64_add_dynamic_entry (info, tag, val) \ : bfd_elf32_add_dynamic_entry (info, tag, val))#else#define MIPS_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \ (ABI_64_P (elf_hash_table (info)->dynobj) \ ? (abort (), false) \ : bfd_elf32_add_dynamic_entry (info, tag, val))#endif/* The number of local .got entries we reserve. */#define MIPS_RESERVED_GOTNO (2)/* Instructions which appear in a stub. For some reason the stub is slightly different on an SGI system. */#define ELF_MIPS_GP_OFFSET(abfd) (SGI_COMPAT (abfd) ? 0x7ff0 : 0x8000)#define STUB_LW(abfd) \ (SGI_COMPAT (abfd) \ ? (ABI_64_P (abfd) \ ? 0xdf998010 /* ld t9,0x8010(gp) */ \ : 0x8f998010) /* lw t9,0x8010(gp) */ \ : 0x8f998010) /* lw t9,0x8000(gp) */#define STUB_MOVE(abfd) \ (SGI_COMPAT (abfd) ? 0x03e07825 : 0x03e07821) /* move t7,ra */#define STUB_JALR 0x0320f809 /* jal t9 */#define STUB_LI16(abfd) \ (SGI_COMPAT (abfd) ? 0x34180000 : 0x24180000) /* ori t8,zero,0 */#define MIPS_FUNCTION_STUB_SIZE (16)#if 0/* We no longer try to identify particular sections for the .dynsym section. When we do, we wind up crashing if there are other random sections with relocations. *//* Names of sections which appear in the .dynsym section in an Irix 5 executable. */static const char * const mips_elf_dynsym_sec_names[] ={ ".text", ".init", ".fini", ".data", ".rodata", ".sdata", ".sbss", ".bss", NULL};#define SIZEOF_MIPS_DYNSYM_SECNAMES \ (sizeof mips_elf_dynsym_sec_names / sizeof mips_elf_dynsym_sec_names[0])/* The number of entries in mips_elf_dynsym_sec_names which go in the text segment. */#define MIPS_TEXT_DYNSYM_SECNO (3)#endif /* 0 *//* The names of the runtime procedure table symbols used on Irix 5. */static const char * const mips_elf_dynsym_rtproc_names[] ={ "_procedure_table", "_procedure_string_table", "_procedure_table_size", NULL};/* These structures are used to generate the .compact_rel section on Irix 5. */typedef struct{ unsigned long id1; /* Always one? */ unsigned long num; /* Number of compact relocation entries. */ unsigned long id2; /* Always two? */ unsigned long offset; /* The file offset of the first relocation. */ unsigned long reserved0; /* Zero? */ unsigned long reserved1; /* Zero? */} Elf32_compact_rel;typedef struct{ bfd_byte id1[4]; bfd_byte num[4]; bfd_byte id2[4]; bfd_byte offset[4]; bfd_byte reserved0[4]; bfd_byte reserved1[4];} Elf32_External_compact_rel;typedef struct{ unsigned int ctype : 1; /* 1: long 0: short format. See below. */ unsigned int rtype : 4; /* Relocation types. See below. */ unsigned int dist2to : 8; unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */ unsigned long konst; /* KONST field. See below. */ unsigned long vaddr; /* VADDR to be relocated. */} Elf32_crinfo;typedef struct{ unsigned int ctype : 1; /* 1: long 0: short format. See below. */ unsigned int rtype : 4; /* Relocation types. See below. */ unsigned int dist2to : 8; unsigned int relvaddr : 19; /* (VADDR - vaddr of the previous entry)/ 4 */ unsigned long konst; /* KONST field. See below. */} Elf32_crinfo2;typedef struct{ bfd_byte info[4]; bfd_byte konst[4]; bfd_byte vaddr[4];} Elf32_External_crinfo;typedef struct{ bfd_byte info[4]; bfd_byte konst[4];} Elf32_External_crinfo2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -