📄 elf-m10300.c
字号:
/* Matsushita 10300 specific support for 32-bit ELF Copyright 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 "libbfd.h"#include "elf-bfd.h"#include "elf/mn10300.h"struct elf32_mn10300_link_hash_entry { /* The basic elf link hash table entry. */ struct elf_link_hash_entry root; /* For function symbols, the number of times this function is called directly (ie by name). */ unsigned int direct_calls; /* For function symbols, the size of this function's stack (if <= 255 bytes). We stuff this into "call" instructions to this target when it's valid and profitable to do so. This does not include stack allocated by movm! */ unsigned char stack_size; /* For function symbols, arguments (if any) for movm instruction in the prologue. We stuff this value into "call" instructions to the target when it's valid and profitable to do so. */ unsigned char movm_args; /* For funtion symbols, the amount of stack space that would be allocated by the movm instruction. This is redundant with movm_args, but we add it to the hash table to avoid computing it over and over. */ unsigned char movm_stack_size;/* When set, convert all "call" instructions to this target into "calls" instructions. */#define MN10300_CONVERT_CALL_TO_CALLS 0x1/* Used to mark functions which have had redundant parts of their prologue deleted. */#define MN10300_DELETED_PROLOGUE_BYTES 0x2 unsigned char flags;};/* We derive a hash table from the main elf linker hash table so we can store state variables and a secondary hash table without resorting to global variables. */struct elf32_mn10300_link_hash_table { /* The main hash table. */ struct elf_link_hash_table root; /* A hash table for static functions. We could derive a new hash table instead of using the full elf32_mn10300_link_hash_table if we wanted to save some memory. */ struct elf32_mn10300_link_hash_table *static_hash_table; /* Random linker state flags. */#define MN10300_HASH_ENTRIES_INITIALIZED 0x1 char flags;};/* For MN10300 linker hash table. *//* Get the MN10300 ELF linker hash table from a link_info structure. */#define elf32_mn10300_hash_table(p) \ ((struct elf32_mn10300_link_hash_table *) ((p)->hash))#define elf32_mn10300_link_hash_traverse(table, func, info) \ (elf_link_hash_traverse \ (&(table)->root, \ (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ (info)))static struct bfd_hash_entry *elf32_mn10300_link_hash_newfunc PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));static struct bfd_link_hash_table *elf32_mn10300_link_hash_table_create PARAMS ((bfd *));static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));static void mn10300_info_to_howto PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));static boolean mn10300_elf_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));static asection *mn10300_elf_gc_mark_hook PARAMS ((bfd *, struct bfd_link_info *info, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean mn10300_elf_relax_delete_bytes PARAMS ((bfd *, asection *, bfd_vma, int));static boolean mn10300_elf_symbol_address_p PARAMS ((bfd *, asection *, Elf32_External_Sym *, bfd_vma));static boolean elf32_mn10300_finish_hash_table_entry PARAMS ((struct bfd_hash_entry *, PTR));static void compute_function_info PARAMS ((bfd *, struct elf32_mn10300_link_hash_entry *, bfd_vma, unsigned char *));/* We have to use RELA instructions since md_apply_fix3 in the assembler does absolutely nothing. */#define USE_RELAstatic reloc_howto_type elf_mn10300_howto_table[] = { /* Dummy relocation. Does nothing. */ HOWTO (R_MN10300_NONE, 0, 2, 16, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_NONE", false, 0, 0, false), /* Standard 32 bit reloc. */ HOWTO (R_MN10300_32, 0, 2, 32, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_32", false, 0xffffffff, 0xffffffff, false), /* Standard 16 bit reloc. */ HOWTO (R_MN10300_16, 0, 1, 16, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_16", false, 0xffff, 0xffff, false), /* Standard 8 bit reloc. */ HOWTO (R_MN10300_8, 0, 0, 8, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_8", false, 0xff, 0xff, false), /* Standard 32bit pc-relative reloc. */ HOWTO (R_MN10300_PCREL32, 0, 2, 32, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_PCREL32", false, 0xffffffff, 0xffffffff, true), /* Standard 16bit pc-relative reloc. */ HOWTO (R_MN10300_PCREL16, 0, 1, 16, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_PCREL16", false, 0xffff, 0xffff, true), /* Standard 8 pc-relative reloc. */ HOWTO (R_MN10300_PCREL8, 0, 0, 8, true, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_PCREL8", false, 0xff, 0xff, true), /* GNU extension to record C++ vtable hierarchy */ HOWTO (R_MN10300_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_MN10300_GNU_VTINHERIT", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* GNU extension to record C++ vtable member usage */ HOWTO (R_MN10300_GNU_VTENTRY, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_MN10300_GNU_VTENTRY", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ /* Standard 24 bit reloc. */ HOWTO (R_MN10300_24, 0, 2, 24, false, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_MN10300_24", false, 0xffffff, 0xffffff, false),};struct mn10300_reloc_map { bfd_reloc_code_real_type bfd_reloc_val; unsigned char elf_reloc_val;};static const struct mn10300_reloc_map mn10300_reloc_map[] = { { BFD_RELOC_NONE, R_MN10300_NONE, }, { BFD_RELOC_32, R_MN10300_32, }, { BFD_RELOC_16, R_MN10300_16, }, { BFD_RELOC_8, R_MN10300_8, }, { BFD_RELOC_32_PCREL, R_MN10300_PCREL32, }, { BFD_RELOC_16_PCREL, R_MN10300_PCREL16, }, { BFD_RELOC_8_PCREL, R_MN10300_PCREL8, }, { BFD_RELOC_24, R_MN10300_24, }, { BFD_RELOC_VTABLE_INHERIT, R_MN10300_GNU_VTINHERIT }, { BFD_RELOC_VTABLE_ENTRY, R_MN10300_GNU_VTENTRY },};static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code;{ unsigned int i; for (i = 0; i < sizeof (mn10300_reloc_map) / sizeof (struct mn10300_reloc_map); i++) { if (mn10300_reloc_map[i].bfd_reloc_val == code) return &elf_mn10300_howto_table[mn10300_reloc_map[i].elf_reloc_val]; } return NULL;}/* Set the howto pointer for an MN10300 ELF reloc. */static voidmn10300_info_to_howto (abfd, cache_ptr, dst) bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf32_Internal_Rela *dst;{ unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); BFD_ASSERT (r_type < (unsigned int) R_MN10300_MAX); cache_ptr->howto = &elf_mn10300_howto_table[r_type];}/* Look through the relocs for a section during the first phase. Since we don't do .gots or .plts, we just need to consider the virtual table relocs for gc. */static booleanmn10300_elf_check_relocs (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs;{ Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; if (info->relocateable) return true; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { struct elf_link_hash_entry *h; unsigned long r_symndx; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; switch (ELF32_R_TYPE (rel->r_info)) { /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_MN10300_GNU_VTINHERIT: if (!_bfd_elf32_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) return false; break; /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_MN10300_GNU_VTENTRY: if (!_bfd_elf32_gc_record_vtentry (abfd, sec, h, rel->r_addend)) return false; break; } } return true;}/* Return the section that should be marked against GC for a given relocation. */static asection *mn10300_elf_gc_mark_hook (abfd, info, rel, h, sym) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym;{ if (h != NULL) { switch (ELF32_R_TYPE (rel->r_info)) { case R_MN10300_GNU_VTINHERIT: case R_MN10300_GNU_VTENTRY: break; default: switch (h->root.type) { case bfd_link_hash_defined: case bfd_link_hash_defweak: return h->root.u.def.section; case bfd_link_hash_common: return h->root.u.c.p->section; default: break; } } } else { if (!(elf_bad_symtab (abfd) && ELF_ST_BIND (sym->st_info) != STB_LOCAL) && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) && sym->st_shndx != SHN_COMMON)) { return bfd_section_from_elf_index (abfd, sym->st_shndx); } } return NULL;}/* Perform a relocation as part of a final link. */static bfd_reloc_status_typemn10300_elf_final_link_relocate (howto, input_bfd, output_bfd, input_section, contents, offset, value, addend, info, sym_sec, is_local) reloc_howto_type *howto; bfd *input_bfd; bfd *output_bfd ATTRIBUTE_UNUSED; asection *input_section; bfd_byte *contents; bfd_vma offset; bfd_vma value; bfd_vma addend; struct bfd_link_info *info ATTRIBUTE_UNUSED; asection *sym_sec ATTRIBUTE_UNUSED; int is_local ATTRIBUTE_UNUSED;{ unsigned long r_type = howto->type; bfd_byte *hit_data = contents + offset; switch (r_type)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -