📄 coff-arm.c
字号:
/* BFD back-end for ARM COFF files. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. Written by Cygnus Support.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 "coff/arm.h"#include "coff/internal.h"#ifdef COFF_WITH_PE#include "coff/pe.h"#endif#include "libcoff.h"/* Macros for manipulation the bits in the flags field of the coff data structure. */#define APCS_26_FLAG( abfd ) (coff_data (abfd)->flags & F_APCS_26)#define APCS_FLOAT_FLAG( abfd ) (coff_data (abfd)->flags & F_APCS_FLOAT)#define PIC_FLAG( abfd ) (coff_data (abfd)->flags & F_PIC)#define APCS_SET( abfd ) (coff_data (abfd)->flags & F_APCS_SET)#define SET_APCS_FLAGS( abfd, flgs) (coff_data (abfd)->flags = \ (coff_data (abfd)->flags & ~ (F_APCS_26 | F_APCS_FLOAT | F_PIC)) \ | (flgs | F_APCS_SET))#define INTERWORK_FLAG( abfd ) (coff_data (abfd)->flags & F_INTERWORK)#define INTERWORK_SET( abfd ) (coff_data (abfd)->flags & F_INTERWORK_SET)#define SET_INTERWORK_FLAG( abfd, flg ) (coff_data (abfd)->flags = \ (coff_data (abfd)->flags & ~ F_INTERWORK) \ | (flg | F_INTERWORK_SET))#ifndef NUM_ELEM#define NUM_ELEM(a) ((sizeof (a)) / sizeof ((a)[0]))#endiftypedef enum {bunknown, b9, b12, b23} thumb_pcrel_branchtype;/* some typedefs for holding instructions */typedef unsigned long int insn32;typedef unsigned short int insn16; /* Forward declarations for stupid compilers. */static boolean coff_arm_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, struct internal_reloc *, struct internal_syment *, asection **));static bfd_reloc_status_type aoutarm_fix_pcrel_26_done PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type aoutarm_fix_pcrel_26 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type coff_thumb_pcrel_23 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type coff_thumb_pcrel_12 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type coff_thumb_pcrel_9 PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static bfd_reloc_status_type coff_arm_reloc PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));static boolean coff_arm_adjust_symndx PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, struct internal_reloc *, boolean *));static reloc_howto_type * coff_arm_rtype_to_howto PARAMS ((bfd *, asection *, struct internal_reloc *, struct coff_link_hash_entry *, struct internal_syment *, bfd_vma *));static bfd_reloc_status_type coff_thumb_pcrel_common PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **, thumb_pcrel_branchtype));static CONST struct reloc_howto_struct * coff_arm_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));static struct bfd_link_hash_table * coff_arm_link_hash_table_create PARAMS ((bfd *));static insn32 insert_thumb_branch PARAMS ((insn32, int));static struct coff_link_hash_entry * find_thumb_glue PARAMS ((struct bfd_link_info *, CONST char *, bfd *));static struct coff_link_hash_entry * find_arm_glue PARAMS ((struct bfd_link_info *, CONST char *, bfd *));#ifndef COFF_IMAGE_WITH_PEstatic void record_arm_to_thumb_glue PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));static void record_thumb_to_arm_glue PARAMS ((struct bfd_link_info *, struct coff_link_hash_entry *));#endifstatic boolean coff_arm_merge_private_bfd_data PARAMS ((bfd *, bfd *));static boolean coff_arm_print_private_bfd_data PARAMS ((bfd *, PTR));static boolean _bfd_coff_arm_set_private_flags PARAMS ((bfd *, flagword));static boolean coff_arm_copy_private_bfd_data PARAMS ((bfd *, bfd *));static boolean coff_arm_is_local_label_name PARAMS ((bfd *, const char *));static boolean coff_arm_link_output_has_begun PARAMS ((bfd *, struct coff_final_link_info *));static boolean coff_arm_final_link_postscript PARAMS ((bfd *, struct coff_final_link_info *));/* 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"/* Used by the assembler. */static bfd_reloc_status_typecoff_arm_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol ATTRIBUTE_UNUSED; PTR data; asection *input_section ATTRIBUTE_UNUSED; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ symvalue diff; if (output_bfd == (bfd *) NULL) return bfd_reloc_continue; diff = reloc_entry->addend;#define DOIT(x) \ x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + diff) & howto->dst_mask)) if (diff != 0) { reloc_howto_type *howto = reloc_entry->howto; unsigned char *addr = (unsigned char *) data + reloc_entry->address; switch (howto->size) { case 0: { char x = bfd_get_8 (abfd, addr); DOIT (x); bfd_put_8 (abfd, x, addr); } break; case 1: { short x = bfd_get_16 (abfd, addr); DOIT (x); bfd_put_16 (abfd, x, addr); } break; case 2: { long x = bfd_get_32 (abfd, addr); DOIT (x); bfd_put_32 (abfd, x, addr); } break; default: abort (); } } /* Now let bfd_perform_relocation finish everything up. */ return bfd_reloc_continue;}/* If USER_LABEL_PREFIX is defined as "_" (see coff_arm_is_local_label_name() in this file), then TARGET_UNDERSCORE should be defined, otherwise it should not. */#ifndef TARGET_UNDERSCORE#define TARGET_UNDERSCORE '_'#endif#ifndef PCRELOFFSET#define PCRELOFFSET true#endif/* These most certainly belong somewhere else. Just had to get rid of the manifest constants in the code. */#define ARM_8 0#define ARM_16 1#define ARM_32 2#define ARM_26 3#define ARM_DISP8 4#define ARM_DISP16 5#define ARM_DISP32 6#define ARM_26D 7/* 8 is unused */#define ARM_NEG16 9#define ARM_NEG32 10#define ARM_RVA32 11#define ARM_THUMB9 12#define ARM_THUMB12 13#define ARM_THUMB23 14#ifdef ARM_WINCE#undef ARM_32#undef ARM_RVA32#undef ARM_26#undef ARM_THUMB12#undef ARM_26D#define ARM_32 1#define ARM_RVA32 2#define ARM_26 3#define ARM_THUMB12 4#define ARM_26D 5#define ARM_SECTION 14#define ARM_SECREL 15#endifstatic reloc_howto_type aoutarm_std_reloc_howto[] ={ /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */#ifdef ARM_WINCE EMPTY_HOWTO (-1), HOWTO (ARM_32, 0, 2, 32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_32", true, 0xffffffff, 0xffffffff, PCRELOFFSET), HOWTO (ARM_RVA32, 0, 2, 32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_RVA32", true, 0xffffffff, 0xffffffff, PCRELOFFSET), HOWTO (ARM_26, 2, 2, 24, true, 0, complain_overflow_signed, aoutarm_fix_pcrel_26 , "ARM_26", false, 0x00ffffff, 0x00ffffff, PCRELOFFSET), HOWTO (ARM_THUMB12, 1, 1, 11, true, 0, complain_overflow_signed, coff_thumb_pcrel_12 , "ARM_THUMB12", false, 0x000007ff, 0x000007ff, PCRELOFFSET), HOWTO (ARM_26D, 2, 2, 24, false, 0, complain_overflow_dont, aoutarm_fix_pcrel_26_done, "ARM_26D", true, 0x00ffffff, 0x0, false), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), EMPTY_HOWTO (-1), HOWTO (ARM_SECTION, 0, 1, 16, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_16", true, 0x0000ffff, 0x0000ffff, PCRELOFFSET), HOWTO (ARM_SECREL, 0, 2, 32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_32", true, 0xffffffff, 0xffffffff, PCRELOFFSET),#else /* not ARM_WINCE */ HOWTO(ARM_8, /* type */ 0, /* rightshift */ 0, /* size */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ coff_arm_reloc, /* special_function */ "ARM_8", /* name */ true, /* partial_inplace */ 0x000000ff, /* src_mask */ 0x000000ff, /* dst_mask */ PCRELOFFSET /* pcrel_offset */), HOWTO(ARM_16, 0, 1, 16, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_16", true, 0x0000ffff, 0x0000ffff, PCRELOFFSET), HOWTO(ARM_32, 0, 2, 32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_32", true, 0xffffffff, 0xffffffff, PCRELOFFSET), HOWTO(ARM_26, 2, 2, 24, true, 0, complain_overflow_signed, aoutarm_fix_pcrel_26 , "ARM_26", false, 0x00ffffff, 0x00ffffff, PCRELOFFSET), HOWTO(ARM_DISP8, 0, 0, 8, true, 0, complain_overflow_signed, coff_arm_reloc, "ARM_DISP8", true, 0x000000ff, 0x000000ff, true), HOWTO( ARM_DISP16, 0, 1, 16, true, 0, complain_overflow_signed, coff_arm_reloc, "ARM_DISP16", true, 0x0000ffff, 0x0000ffff, true), HOWTO( ARM_DISP32, 0, 2, 32, true, 0, complain_overflow_signed, coff_arm_reloc, "ARM_DISP32", true, 0xffffffff, 0xffffffff, true), HOWTO( ARM_26D, 2, 2, 24, false, 0, complain_overflow_dont, aoutarm_fix_pcrel_26_done, "ARM_26D", true, 0x00ffffff, 0x0, false), /* 8 is unused */ EMPTY_HOWTO (-1), HOWTO( ARM_NEG16, 0, -1, 16, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_NEG16", true, 0x0000ffff, 0x0000ffff, false), HOWTO( ARM_NEG32, 0, -2,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -