elf32-m68k.c

来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,163 行 · 第 1/5 页

C
2,163
字号
/* Motorola 68k series support for 32-bit ELF   Copyright 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001   Free Software Foundation, Inc.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.  */#include "bfd.h"#include "sysdep.h"#include "bfdlink.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/m68k.h"static reloc_howto_type *reloc_type_lookup  PARAMS ((bfd *, bfd_reloc_code_real_type));static void rtype_to_howto  PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));static struct bfd_hash_entry *elf_m68k_link_hash_newfunc  PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table *elf_m68k_link_hash_table_create  PARAMS ((bfd *));static boolean elf_m68k_check_relocs  PARAMS ((bfd *, struct bfd_link_info *, asection *,	   const Elf_Internal_Rela *));static asection *elf_m68k_gc_mark_hook  PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *,	   struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean elf_m68k_gc_sweep_hook  PARAMS ((bfd *, struct bfd_link_info *, asection *,	   const Elf_Internal_Rela *));static boolean elf_m68k_adjust_dynamic_symbol  PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static boolean elf_m68k_size_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf_m68k_relocate_section  PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,	   Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static boolean elf_m68k_finish_dynamic_symbol  PARAMS ((bfd *, struct bfd_link_info *, struct elf_link_hash_entry *,	   Elf_Internal_Sym *));static boolean elf_m68k_finish_dynamic_sections  PARAMS ((bfd *, struct bfd_link_info *));static boolean elf32_m68k_set_private_flags  PARAMS ((bfd *, flagword));static boolean elf32_m68k_copy_private_bfd_data  PARAMS ((bfd *, bfd *));static boolean elf32_m68k_merge_private_bfd_data  PARAMS ((bfd *, bfd *));static boolean elf32_m68k_print_private_bfd_data  PARAMS ((bfd *, PTR));static reloc_howto_type howto_table[] = {  HOWTO(R_68K_NONE,       0, 0, 0, false,0, complain_overflow_dont,     bfd_elf_generic_reloc, "R_68K_NONE",      false, 0, 0x00000000,false),  HOWTO(R_68K_32,         0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_32",        false, 0, 0xffffffff,false),  HOWTO(R_68K_16,         0, 1,16, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_16",        false, 0, 0x0000ffff,false),  HOWTO(R_68K_8,          0, 0, 8, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_8",         false, 0, 0x000000ff,false),  HOWTO(R_68K_PC32,       0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PC32",      false, 0, 0xffffffff,true),  HOWTO(R_68K_PC16,       0, 1,16, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PC16",      false, 0, 0x0000ffff,true),  HOWTO(R_68K_PC8,        0, 0, 8, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PC8",       false, 0, 0x000000ff,true),  HOWTO(R_68K_GOT32,      0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32",     false, 0, 0xffffffff,true),  HOWTO(R_68K_GOT16,      0, 1,16, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_GOT16",     false, 0, 0x0000ffff,true),  HOWTO(R_68K_GOT8,       0, 0, 8, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_GOT8",      false, 0, 0x000000ff,true),  HOWTO(R_68K_GOT32O,     0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_GOT32O",    false, 0, 0xffffffff,false),  HOWTO(R_68K_GOT16O,     0, 1,16, false,0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_GOT16O",    false, 0, 0x0000ffff,false),  HOWTO(R_68K_GOT8O,      0, 0, 8, false,0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_GOT8O",     false, 0, 0x000000ff,false),  HOWTO(R_68K_PLT32,      0, 2,32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32",     false, 0, 0xffffffff,true),  HOWTO(R_68K_PLT16,      0, 1,16, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PLT16",     false, 0, 0x0000ffff,true),  HOWTO(R_68K_PLT8,       0, 0, 8, true, 0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PLT8",      false, 0, 0x000000ff,true),  HOWTO(R_68K_PLT32O,     0, 2,32, false,0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_68K_PLT32O",    false, 0, 0xffffffff,false),  HOWTO(R_68K_PLT16O,     0, 1,16, false,0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PLT16O",    false, 0, 0x0000ffff,false),  HOWTO(R_68K_PLT8O,      0, 0, 8, false,0, complain_overflow_signed,   bfd_elf_generic_reloc, "R_68K_PLT8O",     false, 0, 0x000000ff,false),  HOWTO(R_68K_COPY,       0, 0, 0, false,0, complain_overflow_dont,     bfd_elf_generic_reloc, "R_68K_COPY",      false, 0, 0xffffffff,false),  HOWTO(R_68K_GLOB_DAT,   0, 2,32, false,0, complain_overflow_dont,     bfd_elf_generic_reloc, "R_68K_GLOB_DAT",  false, 0, 0xffffffff,false),  HOWTO(R_68K_JMP_SLOT,   0, 2,32, false,0, complain_overflow_dont,     bfd_elf_generic_reloc, "R_68K_JMP_SLOT",  false, 0, 0xffffffff,false),  HOWTO(R_68K_RELATIVE,   0, 2,32, false,0, complain_overflow_dont,     bfd_elf_generic_reloc, "R_68K_RELATIVE",  false, 0, 0xffffffff,false),  /* GNU extension to record C++ vtable hierarchy */  HOWTO (R_68K_GNU_VTINHERIT,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 NULL,			/* special_function */	 "R_68K_GNU_VTINHERIT",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),  /* GNU extension to record C++ vtable member usage */  HOWTO (R_68K_GNU_VTENTRY,	/* type */	 0,			/* rightshift */	 2,			/* size (0 = byte, 1 = short, 2 = long) */	 0,			/* bitsize */	 false,			/* pc_relative */	 0,			/* bitpos */	 complain_overflow_dont, /* complain_on_overflow */	 _bfd_elf_rel_vtable_reloc_fn, /* special_function */	 "R_68K_GNU_VTENTRY",	/* name */	 false,			/* partial_inplace */	 0,			/* src_mask */	 0,			/* dst_mask */	 false),};static voidrtype_to_howto (abfd, cache_ptr, dst)     bfd *abfd ATTRIBUTE_UNUSED;     arelent *cache_ptr;     Elf_Internal_Rela *dst;{  BFD_ASSERT (ELF32_R_TYPE(dst->r_info) < (unsigned int) R_68K_max);  cache_ptr->howto = &howto_table[ELF32_R_TYPE(dst->r_info)];}#define elf_info_to_howto rtype_to_howtostatic const struct{  bfd_reloc_code_real_type bfd_val;  int elf_val;} reloc_map[] = {  { BFD_RELOC_NONE, R_68K_NONE },  { BFD_RELOC_32, R_68K_32 },  { BFD_RELOC_16, R_68K_16 },  { BFD_RELOC_8, R_68K_8 },  { BFD_RELOC_32_PCREL, R_68K_PC32 },  { BFD_RELOC_16_PCREL, R_68K_PC16 },  { BFD_RELOC_8_PCREL, R_68K_PC8 },  { BFD_RELOC_32_GOT_PCREL, R_68K_GOT32 },  { BFD_RELOC_16_GOT_PCREL, R_68K_GOT16 },  { BFD_RELOC_8_GOT_PCREL, R_68K_GOT8 },  { BFD_RELOC_32_GOTOFF, R_68K_GOT32O },  { BFD_RELOC_16_GOTOFF, R_68K_GOT16O },  { BFD_RELOC_8_GOTOFF, R_68K_GOT8O },  { BFD_RELOC_32_PLT_PCREL, R_68K_PLT32 },  { BFD_RELOC_16_PLT_PCREL, R_68K_PLT16 },  { BFD_RELOC_8_PLT_PCREL, R_68K_PLT8 },  { BFD_RELOC_32_PLTOFF, R_68K_PLT32O },  { BFD_RELOC_16_PLTOFF, R_68K_PLT16O },  { BFD_RELOC_8_PLTOFF, R_68K_PLT8O },  { BFD_RELOC_NONE, R_68K_COPY },  { BFD_RELOC_68K_GLOB_DAT, R_68K_GLOB_DAT },  { BFD_RELOC_68K_JMP_SLOT, R_68K_JMP_SLOT },  { BFD_RELOC_68K_RELATIVE, R_68K_RELATIVE },  { BFD_RELOC_CTOR, R_68K_32 },  { BFD_RELOC_VTABLE_INHERIT, R_68K_GNU_VTINHERIT },  { BFD_RELOC_VTABLE_ENTRY, R_68K_GNU_VTENTRY },};static reloc_howto_type *reloc_type_lookup (abfd, code)     bfd *abfd ATTRIBUTE_UNUSED;     bfd_reloc_code_real_type code;{  unsigned int i;  for (i = 0; i < sizeof (reloc_map) / sizeof (reloc_map[0]); i++)    {      if (reloc_map[i].bfd_val == code)	return &howto_table[reloc_map[i].elf_val];    }  return 0;}#define bfd_elf32_bfd_reloc_type_lookup reloc_type_lookup#define ELF_ARCH bfd_arch_m68k/* end code generated by elf.el */#define USE_RELA/* Functions for the m68k ELF linker.  *//* The name of the dynamic interpreter.  This is put in the .interp   section.  */#define ELF_DYNAMIC_INTERPRETER "/usr/lib/libc.so.1"/* The size in bytes of an entry in the procedure linkage table.  */#define PLT_ENTRY_SIZE 20/* The first entry in a procedure linkage table looks like this.  See   the SVR4 ABI m68k supplement to see how this works.  */static const bfd_byte elf_m68k_plt0_entry[PLT_ENTRY_SIZE] ={  0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */  0, 0, 0, 0,		  /* replaced with offset to .got + 4.  */  0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,addr]) */  0, 0, 0, 0,		  /* replaced with offset to .got + 8.  */  0, 0, 0, 0		  /* pad out to 20 bytes.  */};/* Subsequent entries in a procedure linkage table look like this.  */static const bfd_byte elf_m68k_plt_entry[PLT_ENTRY_SIZE] ={  0x4e, 0xfb, 0x01, 0x71, /* jmp ([%pc,symbol@GOTPC]) */  0, 0, 0, 0,		  /* replaced with offset to symbol's .got entry.  */  0x2f, 0x3c,		  /* move.l #offset,-(%sp) */  0, 0, 0, 0,		  /* replaced with offset into relocation table.  */  0x60, 0xff,		  /* bra.l .plt */  0, 0, 0, 0		  /* replaced with offset to start of .plt.  */};#define CPU32_FLAG(abfd)  (elf_elfheader (abfd)->e_flags & EF_CPU32)#define PLT_CPU32_ENTRY_SIZE 24/* Procedure linkage table entries for the cpu32 */static const bfd_byte elf_cpu32_plt0_entry[PLT_CPU32_ENTRY_SIZE] ={  0x2f, 0x3b, 0x01, 0x70, /* move.l (%pc,addr),-(%sp) */  0, 0, 0, 0,             /* replaced with offset to .got + 4.  */  0x22, 0x7b, 0x01, 0x70, /* moveal %pc@(0xc), %a1 */  0, 0, 0, 0,             /* replace with offset to .got +8.  */  0x4e, 0xd1,             /* jmp %a1@ */  0, 0, 0, 0,             /* pad out to 24 bytes.  */  0, 0};static const bfd_byte elf_cpu32_plt_entry[PLT_CPU32_ENTRY_SIZE] ={  0x22, 0x7b, 0x01, 0x70,  /* moveal %pc@(0xc), %a1 */  0, 0, 0, 0,              /* replaced with offset to symbol's .got entry.  */  0x4e, 0xd1,              /* jmp %a1@ */  0x2f, 0x3c,              /* move.l #offset,-(%sp) */  0, 0, 0, 0,              /* replaced with offset into relocation table.  */  0x60, 0xff,              /* bra.l .plt */  0, 0, 0, 0,              /* replaced with offset to start of .plt.  */  0, 0};/* The m68k linker needs to keep track of the number of relocs that it   decides to copy in check_relocs for each symbol.  This is so that it   can discard PC relative relocs if it doesn't need them when linking   with -Bsymbolic.  We store the information in a field extending the   regular ELF linker hash table.  *//* This structure keeps track of the number of PC relative relocs we have   copied for a given symbol.  */struct elf_m68k_pcrel_relocs_copied{  /* Next section.  */  struct elf_m68k_pcrel_relocs_copied *next;  /* A section in dynobj.  */  asection *section;  /* Number of relocs copied in this section.  */  bfd_size_type count;};/* m68k ELF linker hash entry.  */struct elf_m68k_link_hash_entry{  struct elf_link_hash_entry root;  /* Number of PC relative relocs copied for this symbol.  */  struct elf_m68k_pcrel_relocs_copied *pcrel_relocs_copied;};/* m68k ELF linker hash table.  */struct elf_m68k_link_hash_table{  struct elf_link_hash_table root;};/* Declare this now that the above structures are defined.  */static boolean elf_m68k_discard_copies  PARAMS ((struct elf_m68k_link_hash_entry *, PTR));/* Traverse an m68k ELF linker hash table.  */#define elf_m68k_link_hash_traverse(table, func, info)			\  (elf_link_hash_traverse						\   (&(table)->root,							\    (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func),	\    (info)))/* Get the m68k ELF linker hash table from a link_info structure.  */#define elf_m68k_hash_table(p) \  ((struct elf_m68k_link_hash_table *) (p)->hash)/* Create an entry in an m68k ELF linker hash table.  */static struct bfd_hash_entry *elf_m68k_link_hash_newfunc (entry, table, string)     struct bfd_hash_entry *entry;     struct bfd_hash_table *table;     const char *string;{  struct elf_m68k_link_hash_entry *ret =    (struct elf_m68k_link_hash_entry *) entry;  /* Allocate the structure if it has not already been allocated by a     subclass.  */  if (ret == (struct elf_m68k_link_hash_entry *) NULL)    ret = ((struct elf_m68k_link_hash_entry *)	   bfd_hash_allocate (table,			      sizeof (struct elf_m68k_link_hash_entry)));  if (ret == (struct elf_m68k_link_hash_entry *) NULL)    return (struct bfd_hash_entry *) ret;  /* Call the allocation method of the superclass.  */  ret = ((struct elf_m68k_link_hash_entry *)	 _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,				     table, string));  if (ret != (struct elf_m68k_link_hash_entry *) NULL)    {      ret->pcrel_relocs_copied = NULL;    }  return (struct bfd_hash_entry *) ret;}/* Create an m68k ELF linker hash table.  */static struct bfd_link_hash_table *elf_m68k_link_hash_table_create (abfd)     bfd *abfd;{  struct elf_m68k_link_hash_table *ret;  ret = ((struct elf_m68k_link_hash_table *)	 bfd_alloc (abfd, sizeof (struct elf_m68k_link_hash_table)));  if (ret == (struct elf_m68k_link_hash_table *) NULL)    return NULL;  if (! _bfd_elf_link_hash_table_init (&ret->root, abfd,				       elf_m68k_link_hash_newfunc))    {      bfd_release (abfd, ret);      return NULL;    }  return &ret->root.root;}/* Keep m68k-specific flags in the ELF header */static booleanelf32_m68k_set_private_flags (abfd, flags)     bfd *abfd;     flagword flags;{  elf_elfheader (abfd)->e_flags = flags;  elf_flags_init (abfd) = true;  return true;}/* Copy m68k-specific data from one module to another */static booleanelf32_m68k_copy_private_bfd_data (ibfd, obfd)     bfd *ibfd;     bfd *obfd;{  flagword in_flags;  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)    return true;  in_flags = elf_elfheader (ibfd)->e_flags;  elf_elfheader (obfd)->e_flags = in_flags;  elf_flags_init (obfd) = true;  return true;}/* Merge backend specific data from an object file to the output   object file when linking.  */static booleanelf32_m68k_merge_private_bfd_data (ibfd, obfd)     bfd *ibfd;     bfd *obfd;{  flagword out_flags;  flagword in_flags;  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour      || bfd_get_flavour (obfd) != bfd_target_elf_flavour)    return true;  in_flags  = elf_elfheader (ibfd)->e_flags;  out_flags = elf_elfheader (obfd)->e_flags;  if (!elf_flags_init (obfd))    {      elf_flags_init (obfd) = true;      elf_elfheader (obfd)->e_flags = in_flags;    }  return true;}/* Display the flags field */static booleanelf32_m68k_print_private_bfd_data (abfd, ptr)     bfd *abfd;     PTR ptr;{  FILE *file = (FILE *) ptr;  BFD_ASSERT (abfd != NULL && ptr != NULL);  /* Print normal ELF private data.  */  _bfd_elf_print_private_bfd_data (abfd, ptr);  /* Ignore init flag - it may not be set, despite the flags field containing valid data.  */  /* xgettext:c-format */  fprintf (file, _ ("private flags = %lx:"), elf_elfheader (abfd)->e_flags);  if (elf_elfheader (abfd)->e_flags & EF_CPU32)    fprintf (file, _ (" [cpu32]"));

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?