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 + -
显示快捷键?