?? elf32-arm.h
字號:
/* 32-bit ELF support for ARM Copyright 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 modify it under the terms of the GNU General Public License as published by the 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 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. */typedef unsigned long int insn32;typedef unsigned short int insn16;static boolean elf32_arm_set_private_flags PARAMS ((bfd *, flagword));static boolean elf32_arm_copy_private_bfd_data PARAMS ((bfd *, bfd *));static boolean elf32_arm_merge_private_bfd_data PARAMS ((bfd *, bfd *));static boolean elf32_arm_print_private_bfd_data PARAMS ((bfd *, PTR));static int elf32_arm_get_symbol_type PARAMS (( Elf_Internal_Sym *, int));static struct bfd_link_hash_table *elf32_arm_link_hash_table_create PARAMS ((bfd *));static bfd_reloc_status_type elf32_arm_final_link_relocate PARAMS ((reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *, const char *, unsigned char, struct elf_link_hash_entry *));static insn32 insert_thumb_branch PARAMS ((insn32, int));static struct elf_link_hash_entry *find_thumb_glue PARAMS ((struct bfd_link_info *, CONST char *, bfd *));static struct elf_link_hash_entry *find_arm_glue PARAMS ((struct bfd_link_info *, CONST char *, bfd *));static void record_arm_to_thumb_glue PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static void record_thumb_to_arm_glue PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *));static void elf32_arm_post_process_headers PARAMS ((bfd *, struct bfd_link_info *));static int elf32_arm_to_thumb_stub PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *, bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));static int elf32_thumb_to_arm_stub PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *, bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma));#define INTERWORK_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_INTERWORK)/* The linker script knows the section names for placement. The entry_names are used to do simple name mangling on the stubs. Given a function name, and its type, the stub can be found. The name can be changed. The only requirement is the %s be present. */#define THUMB2ARM_GLUE_SECTION_NAME ".glue_7t"#define THUMB2ARM_GLUE_ENTRY_NAME "__%s_from_thumb"#define ARM2THUMB_GLUE_SECTION_NAME ".glue_7"#define ARM2THUMB_GLUE_ENTRY_NAME "__%s_from_arm"/* The name of the dynamic interpreter. This is put in the .interp section. */#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"/* The size in bytes of an entry in the procedure linkage table. */#define PLT_ENTRY_SIZE 16/* The first entry in a procedure linkage table looks like this. It is set up so that any shared library function that is called before the relocation has been set up calls the dynamic linker first. */static const unsigned long elf32_arm_plt0_entry [PLT_ENTRY_SIZE / 4] ={ 0xe52de004, /* str lr, [sp, #-4]! */ 0xe59fe010, /* ldr lr, [pc, #16] */ 0xe08fe00e, /* add lr, pc, lr */ 0xe5bef008 /* ldr pc, [lr, #8]! */};/* Subsequent entries in a procedure linkage table look like this. */static const unsigned long elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] ={ 0xe59fc004, /* ldr ip, [pc, #4] */ 0xe08fc00c, /* add ip, pc, ip */ 0xe59cf000, /* ldr pc, [ip] */ 0x00000000 /* offset to symbol in got */};/* The ARM 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 elf32_arm_pcrel_relocs_copied{ /* Next section. */ struct elf32_arm_pcrel_relocs_copied * next; /* A section in dynobj. */ asection * section; /* Number of relocs copied in this section. */ bfd_size_type count;};/* Arm ELF linker hash entry. */struct elf32_arm_link_hash_entry{ struct elf_link_hash_entry root; /* Number of PC relative relocs copied for this symbol. */ struct elf32_arm_pcrel_relocs_copied * pcrel_relocs_copied;};/* Declare this now that the above structures are defined. */static boolean elf32_arm_discard_copies PARAMS ((struct elf32_arm_link_hash_entry *, PTR));/* Traverse an arm ELF linker hash table. */#define elf32_arm_link_hash_traverse(table, func, info) \ (elf_link_hash_traverse \ (&(table)->root, \ (boolean (*) PARAMS ((struct elf_link_hash_entry *, PTR))) (func), \ (info)))/* Get the ARM elf linker hash table from a link_info structure. */#define elf32_arm_hash_table(info) \ ((struct elf32_arm_link_hash_table *) ((info)->hash))/* ARM ELF linker hash table. */struct elf32_arm_link_hash_table{ /* The main hash table. */ struct elf_link_hash_table root; /* The size in bytes of the section containg the Thumb-to-ARM glue. */ long int thumb_glue_size; /* The size in bytes of the section containg the ARM-to-Thumb glue. */ long int arm_glue_size; /* An arbitary input BFD chosen to hold the glue sections. */ bfd * bfd_of_glue_owner; /* A boolean indicating whether knowledge of the ARM's pipeline length should be applied by the linker. */ int no_pipeline_knowledge;};/* Create an entry in an ARM ELF linker hash table. */static struct bfd_hash_entry *elf32_arm_link_hash_newfunc (entry, table, string) struct bfd_hash_entry * entry; struct bfd_hash_table * table; const char * string;{ struct elf32_arm_link_hash_entry * ret = (struct elf32_arm_link_hash_entry *) entry; /* Allocate the structure if it has not already been allocated by a subclass. */ if (ret == (struct elf32_arm_link_hash_entry *) NULL) ret = ((struct elf32_arm_link_hash_entry *) bfd_hash_allocate (table, sizeof (struct elf32_arm_link_hash_entry))); if (ret == (struct elf32_arm_link_hash_entry *) NULL) return (struct bfd_hash_entry *) ret; /* Call the allocation method of the superclass. */ ret = ((struct elf32_arm_link_hash_entry *) _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); if (ret != (struct elf32_arm_link_hash_entry *) NULL) ret->pcrel_relocs_copied = NULL; return (struct bfd_hash_entry *) ret;}/* Create an ARM elf linker hash table. */static struct bfd_link_hash_table *elf32_arm_link_hash_table_create (abfd) bfd *abfd;{ struct elf32_arm_link_hash_table *ret; ret = ((struct elf32_arm_link_hash_table *) bfd_alloc (abfd, sizeof (struct elf32_arm_link_hash_table))); if (ret == (struct elf32_arm_link_hash_table *) NULL) return NULL; if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, elf32_arm_link_hash_newfunc)) { bfd_release (abfd, ret); return NULL; } ret->thumb_glue_size = 0; ret->arm_glue_size = 0; ret->bfd_of_glue_owner = NULL; ret->no_pipeline_knowledge = 0; return &ret->root.root;}/* Locate the Thumb encoded calling stub for NAME. */static struct elf_link_hash_entry *find_thumb_glue (link_info, name, input_bfd) struct bfd_link_info *link_info; CONST char *name; bfd *input_bfd;{ char *tmp_name; struct elf_link_hash_entry *hash; struct elf32_arm_link_hash_table *hash_table; /* We need a pointer to the armelf specific hash table. */ hash_table = elf32_arm_hash_table (link_info); tmp_name = ((char *) bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1)); BFD_ASSERT (tmp_name); sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name); hash = elf_link_hash_lookup (&(hash_table)->root, tmp_name, false, false, true); if (hash == NULL) /* xgettext:c-format */ _bfd_error_handler (_("%s: unable to find THUMB glue '%s' for `%s'"), bfd_get_filename (input_bfd), tmp_name, name); free (tmp_name); return hash;}/* Locate the ARM encoded calling stub for NAME. */static struct elf_link_hash_entry *find_arm_glue (link_info, name, input_bfd) struct bfd_link_info *link_info; CONST char *name; bfd *input_bfd;{ char *tmp_name; struct elf_link_hash_entry *myh; struct elf32_arm_link_hash_table *hash_table; /* We need a pointer to the elfarm specific hash table. */ hash_table = elf32_arm_hash_table (link_info); tmp_name = ((char *) bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1)); BFD_ASSERT (tmp_name); sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name); myh = elf_link_hash_lookup (&(hash_table)->root, tmp_name, false, false, true); if (myh == NULL) /* xgettext:c-format */ _bfd_error_handler (_("%s: unable to find ARM glue '%s' for `%s'"), bfd_get_filename (input_bfd), tmp_name, name); free (tmp_name); return myh;}/* ARM->Thumb glue: .arm __func_from_arm: ldr r12, __func_addr bx r12 __func_addr: .word func @ behave as if you saw a ARM_32 reloc. */#define ARM2THUMB_GLUE_SIZE 12static const insn32 a2t1_ldr_insn = 0xe59fc000;static const insn32 a2t2_bx_r12_insn = 0xe12fff1c;static const insn32 a2t3_func_addr_insn = 0x00000001;/* Thumb->ARM: Thumb->(non-interworking aware) ARM .thumb .thumb .align 2 .align 2 __func_from_thumb: __func_from_thumb: bx pc push {r6, lr} nop ldr r6, __func_addr .arm mov lr, pc __func_change_to_arm: bx r6 b func .arm __func_back_to_thumb: ldmia r13! {r6, lr} bx lr __func_addr: .word func */#define THUMB2ARM_GLUE_SIZE 8static const insn16 t2a1_bx_pc_insn = 0x4778;static const insn16 t2a2_noop_insn = 0x46c0;static const insn32 t2a3_b_insn = 0xea000000;static const insn16 t2a1_push_insn = 0xb540;static const insn16 t2a2_ldr_insn = 0x4e03;static const insn16 t2a3_mov_insn = 0x46fe;static const insn16 t2a4_bx_insn = 0x4730;static const insn32 t2a5_pop_insn = 0xe8bd4040;static const insn32 t2a6_bx_insn = 0xe12fff1e;booleanbfd_elf32_arm_allocate_interworking_sections (info) struct bfd_link_info * info;{ asection * s; bfd_byte * foo; struct elf32_arm_link_hash_table * globals; globals = elf32_arm_hash_table (info); BFD_ASSERT (globals != NULL); if (globals->arm_glue_size != 0) { BFD_ASSERT (globals->bfd_of_glue_owner != NULL); s = bfd_get_section_by_name (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner, globals->arm_glue_size); s->_raw_size = s->_cooked_size = globals->arm_glue_size; s->contents = foo; } if (globals->thumb_glue_size != 0) { BFD_ASSERT (globals->bfd_of_glue_owner != NULL); s = bfd_get_section_by_name (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); foo = (bfd_byte *) bfd_alloc (globals->bfd_of_glue_owner, globals->thumb_glue_size); s->_raw_size = s->_cooked_size = globals->thumb_glue_size; s->contents = foo; } return true;}static voidrecord_arm_to_thumb_glue (link_info, h) struct bfd_link_info * link_info; struct elf_link_hash_entry * h;{ const char * name = h->root.root.string; register asection * s; char * tmp_name; struct elf_link_hash_entry * myh; struct elf32_arm_link_hash_table * globals; globals = elf32_arm_hash_table (link_info); BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); s = bfd_get_section_by_name (globals->bfd_of_glue_owner, ARM2THUMB_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); tmp_name = ((char *) bfd_malloc (strlen (name) + strlen (ARM2THUMB_GLUE_ENTRY_NAME) + 1)); BFD_ASSERT (tmp_name); sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name); myh = elf_link_hash_lookup (&(globals)->root, tmp_name, false, false, true); if (myh != NULL) { /* We've already seen this guy. */ free (tmp_name); return; } /* The only trick here is using hash_table->arm_glue_size as the value. Even though the section isn't allocated yet, this is where we will be putting it. */ _bfd_generic_link_add_one_symbol (link_info, globals->bfd_of_glue_owner, tmp_name, BSF_GLOBAL, s, globals->arm_glue_size + 1, NULL, true, false, (struct bfd_link_hash_entry **) &myh); free (tmp_name); globals->arm_glue_size += ARM2THUMB_GLUE_SIZE; return;}static voidrecord_thumb_to_arm_glue (link_info, h) struct bfd_link_info *link_info; struct elf_link_hash_entry *h;{ const char *name = h->root.root.string; register asection *s; char *tmp_name; struct elf_link_hash_entry *myh;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -