📄 coff-arm.c
字号:
32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_NEG32", true, 0xffffffff, 0xffffffff, false), HOWTO( ARM_RVA32, 0, 2, 32, false, 0, complain_overflow_bitfield, coff_arm_reloc, "ARM_RVA32", true, 0xffffffff, 0xffffffff, PCRELOFFSET), HOWTO( ARM_THUMB9, 1, 1, 8, true, 0, complain_overflow_signed, coff_thumb_pcrel_9 , "ARM_THUMB9", false, 0x000000ff, 0x000000ff, PCRELOFFSET), HOWTO( ARM_THUMB12, 1, 1, 11, true, 0, complain_overflow_signed, coff_thumb_pcrel_12 , "ARM_THUMB12", false, 0x000007ff, 0x000007ff, PCRELOFFSET), HOWTO( ARM_THUMB23, 1, 2, 22, true, 0, complain_overflow_signed, coff_thumb_pcrel_23 , "ARM_THUMB23", false, 0x07ff07ff, 0x07ff07ff, PCRELOFFSET)#endif /* not ARM_WINCE */};#define NUM_RELOCS NUM_ELEM (aoutarm_std_reloc_howto)#ifdef COFF_WITH_PE/* Return true if this relocation should appear in the output .reloc section. */static booleanin_reloc_p (abfd, howto) bfd * abfd ATTRIBUTE_UNUSED; reloc_howto_type * howto;{ return !howto->pc_relative && howto->type != ARM_RVA32;}#endif#define RTYPE2HOWTO(cache_ptr, dst) \ (cache_ptr)->howto = \ (dst)->r_type < NUM_RELOCS \ ? aoutarm_std_reloc_howto + (dst)->r_type \ : NULL#define coff_rtype_to_howto coff_arm_rtype_to_howtostatic reloc_howto_type *coff_arm_rtype_to_howto (abfd, sec, rel, h, sym, addendp) bfd *abfd ATTRIBUTE_UNUSED; asection *sec; struct internal_reloc *rel; struct coff_link_hash_entry *h ATTRIBUTE_UNUSED; struct internal_syment *sym ATTRIBUTE_UNUSED; bfd_vma *addendp;{ reloc_howto_type * howto; if (rel->r_type >= NUM_RELOCS) return NULL; howto = aoutarm_std_reloc_howto + rel->r_type; if (rel->r_type == ARM_RVA32) *addendp -= pe_data (sec->output_section->owner)->pe_opthdr.ImageBase; return howto;}/* Used by the assembler. */static bfd_reloc_status_typeaoutarm_fix_pcrel_26_done (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry ATTRIBUTE_UNUSED; asymbol *symbol ATTRIBUTE_UNUSED; PTR data ATTRIBUTE_UNUSED; asection *input_section ATTRIBUTE_UNUSED; bfd *output_bfd ATTRIBUTE_UNUSED; char **error_message ATTRIBUTE_UNUSED;{ /* This is dead simple at present. */ return bfd_reloc_ok;}/* Used by the assembler. */static bfd_reloc_status_typeaoutarm_fix_pcrel_26 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ bfd_vma relocation; bfd_size_type addr = reloc_entry->address; long target = bfd_get_32 (abfd, (bfd_byte *) data + addr); bfd_reloc_status_type flag = bfd_reloc_ok; /* If this is an undefined symbol, return error */ if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0) return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined; /* If the sections are different, and we are doing a partial relocation, just ignore it for now. */ if (symbol->section->name != input_section->name && output_bfd != (bfd *)NULL) return bfd_reloc_continue; relocation = (target & 0x00ffffff) << 2; relocation = (relocation ^ 0x02000000) - 0x02000000; /* Sign extend */ relocation += symbol->value; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; relocation -= input_section->output_section->vma; relocation -= input_section->output_offset; relocation -= addr; if (relocation & 3) return bfd_reloc_overflow; /* Check for overflow */ if (relocation & 0x02000000) { if ((relocation & ~ (bfd_vma) 0x03ffffff) != ~ (bfd_vma) 0x03ffffff) flag = bfd_reloc_overflow; } else if (relocation & ~0x03ffffff) flag = bfd_reloc_overflow; target &= ~0x00ffffff; target |= (relocation >> 2) & 0x00ffffff; bfd_put_32 (abfd, target, (bfd_byte *) data + addr); /* Now the ARM magic... Change the reloc type so that it is marked as done. Strictly this is only necessary if we are doing a partial relocation. */ reloc_entry->howto = &aoutarm_std_reloc_howto[ARM_26D]; return flag;}static bfd_reloc_status_typecoff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, btype) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED; thumb_pcrel_branchtype btype;{ bfd_vma relocation = 0; bfd_size_type addr = reloc_entry->address; long target = bfd_get_32 (abfd, (bfd_byte *) data + addr); bfd_reloc_status_type flag = bfd_reloc_ok; bfd_vma dstmsk; bfd_vma offmsk; bfd_vma signbit; /* NOTE: This routine is currently used by GAS, but not by the link phase. */ switch (btype) { case b9: dstmsk = 0x000000ff; offmsk = 0x000001fe; signbit = 0x00000100; break; case b12: dstmsk = 0x000007ff; offmsk = 0x00000ffe; signbit = 0x00000800; break; case b23: dstmsk = 0x07ff07ff; offmsk = 0x007fffff; signbit = 0x00400000; break; default: abort (); } /* If this is an undefined symbol, return error */ if (symbol->section == &bfd_und_section && (symbol->flags & BSF_WEAK) == 0) return output_bfd ? bfd_reloc_continue : bfd_reloc_undefined; /* If the sections are different, and we are doing a partial relocation, just ignore it for now. */ if (symbol->section->name != input_section->name && output_bfd != (bfd *)NULL) return bfd_reloc_continue; switch (btype) { case b9: case b12: relocation = ((target & dstmsk) << 1); break; case b23: if (bfd_big_endian (abfd)) relocation = ((target & 0x7ff) << 1) | ((target & 0x07ff0000) >> 4); else relocation = ((target & 0x7ff) << 12) | ((target & 0x07ff0000) >> 15); break; default: abort (); } relocation = (relocation ^ signbit) - signbit; /* Sign extend */ relocation += symbol->value; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; relocation -= input_section->output_section->vma; relocation -= input_section->output_offset; relocation -= addr; if (relocation & 1) return bfd_reloc_overflow; /* Check for overflow */ if (relocation & signbit) { if ((relocation & ~offmsk) != ~offmsk) flag = bfd_reloc_overflow; } else if (relocation & ~offmsk) flag = bfd_reloc_overflow; target &= ~dstmsk; switch (btype) { case b9: case b12: target |= (relocation >> 1); break; case b23: if (bfd_big_endian (abfd)) target |= ((relocation & 0xfff) >> 1) | ((relocation << 4) & 0x07ff0000); else target |= ((relocation & 0xffe) << 15) | ((relocation >> 12) & 0x7ff); break; default: abort (); } bfd_put_32 (abfd, target, (bfd_byte *) data + addr); /* Now the ARM magic... Change the reloc type so that it is marked as done. Strictly this is only necessary if we are doing a partial relocation. */ reloc_entry->howto = & aoutarm_std_reloc_howto [ARM_26D]; /* TODO: We should possibly have DONE entries for the THUMB PCREL relocations */ return flag;}static bfd_reloc_status_typecoff_thumb_pcrel_23 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, b23);}static bfd_reloc_status_typecoff_thumb_pcrel_12 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, b12);}static bfd_reloc_status_typecoff_thumb_pcrel_9 (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ return coff_thumb_pcrel_common (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message, b9);}static CONST struct reloc_howto_struct *coff_arm_reloc_type_lookup (abfd, code) bfd * abfd; bfd_reloc_code_real_type code;{#define ASTD(i,j) case i: return aoutarm_std_reloc_howto + j if (code == BFD_RELOC_CTOR) switch (bfd_get_arch_info (abfd)->bits_per_address) { case 32: code = BFD_RELOC_32; break; default: return (CONST struct reloc_howto_struct *) 0; } switch (code) {#ifdef ARM_WINCE ASTD (BFD_RELOC_32, ARM_32); ASTD (BFD_RELOC_RVA, ARM_RVA32); ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26); ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12);#else ASTD (BFD_RELOC_8, ARM_8); ASTD (BFD_RELOC_16, ARM_16); ASTD (BFD_RELOC_32, ARM_32); ASTD (BFD_RELOC_ARM_PCREL_BRANCH, ARM_26); ASTD (BFD_RELOC_ARM_PCREL_BLX, ARM_26); ASTD (BFD_RELOC_8_PCREL, ARM_DISP8); ASTD (BFD_RELOC_16_PCREL, ARM_DISP16); ASTD (BFD_RELOC_32_PCREL, ARM_DISP32); ASTD (BFD_RELOC_RVA, ARM_RVA32); ASTD (BFD_RELOC_THUMB_PCREL_BRANCH9, ARM_THUMB9); ASTD (BFD_RELOC_THUMB_PCREL_BRANCH12, ARM_THUMB12); ASTD (BFD_RELOC_THUMB_PCREL_BRANCH23, ARM_THUMB23); ASTD (BFD_RELOC_THUMB_PCREL_BLX, ARM_THUMB23);#endif default: return (CONST struct reloc_howto_struct *) 0; }}#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)#define COFF_PAGE_SIZE 0x1000/* Turn a howto into a reloc nunmber */#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }#define BADMAG(x) ARMBADMAG(x)#define ARM 1 /* Customize coffcode.h *//* Extend the coff_link_hash_table structure with a few ARM specific fields. This allows us to store global data here without actually creating any global variables, which is a no-no in the BFD world. */struct coff_arm_link_hash_table{ /* The original coff_link_hash_table structure. MUST be first field. */ struct coff_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; /* Support interworking with old, non-interworking aware ARM code. */ int support_old_code;};/* Get the ARM coff linker hash table from a link_info structure. */#define coff_arm_hash_table(info) \ ((struct coff_arm_link_hash_table *) ((info)->hash))/* Create an ARM coff linker hash table. */static struct bfd_link_hash_table *coff_arm_link_hash_table_create (abfd) bfd * abfd;{ struct coff_arm_link_hash_table * ret; ret = ((struct coff_arm_link_hash_table *) bfd_alloc (abfd, sizeof (struct coff_arm_link_hash_table))); if (ret == (struct coff_arm_link_hash_table *) NULL) return NULL; if (! _bfd_coff_link_hash_table_init (& ret->root, abfd, _bfd_coff_link_hash_newfunc)) { bfd_release (abfd, ret); return (struct bfd_link_hash_table *) NULL; } ret->thumb_glue_size = 0; ret->arm_glue_size = 0; ret->bfd_of_glue_owner = NULL; return & ret->root.root;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -