X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-arm.h;h=8818c64973437ec443fa81e3822f9767ab422556;hb=517662d4e065860527fbb57f57bad9c076af4b9f;hp=a4e0e906d2506b27dccd28047b4f04dffe0e63b3;hpb=8f615d07046056cd62e6916b1af80223df8641e8;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index a4e0e906d2..8818c64973 100644 --- a/bfd/elf32-arm.h +++ b/bfd/elf32-arm.h @@ -1,5 +1,5 @@ /* 32-bit ELF support for ARM - Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -92,7 +92,7 @@ boolean bfd_elf32_arm_get_bfd_for_interworking boolean bfd_elf32_arm_process_before_allocation PARAMS ((bfd *, struct bfd_link_info *, int)); static enum elf_reloc_type_class elf32_arm_reloc_type_class - PARAMS ((int)); + PARAMS ((const Elf_Internal_Rela *)); #define INTERWORK_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK) @@ -420,7 +420,7 @@ record_arm_to_thumb_glue (link_info, h) struct elf_link_hash_entry * h; { const char * name = h->root.root.string; - register asection * s; + asection * s; char * tmp_name; struct elf_link_hash_entry * myh; struct elf32_arm_link_hash_table * globals; @@ -475,7 +475,7 @@ record_thumb_to_arm_glue (link_info, h) struct elf_link_hash_entry *h; { const char *name = h->root.root.string; - register asection *s; + asection *s; char *tmp_name; struct elf_link_hash_entry *myh; struct elf32_arm_link_hash_table *hash_table; @@ -1116,6 +1116,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, /* When generating a shared object, these relocations are copied into the output file to be resolved at run time. */ if (info->shared + && r_symndx != 0 && (r_type != R_ARM_PC24 || (h != NULL && h->dynindx != -1 @@ -1148,22 +1149,11 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, skip = false; - if (elf_section_data (input_section)->stab_info == NULL) - outrel.r_offset = rel->r_offset; - else - { - bfd_vma off; - - off = (_bfd_stab_section_offset - (output_bfd, &elf_hash_table (info)->stab_info, - input_section, - & elf_section_data (input_section)->stab_info, - rel->r_offset)); - if (off == (bfd_vma) -1) - skip = true; - outrel.r_offset = off; - } - + outrel.r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset); + if (outrel.r_offset == (bfd_vma) -1) + skip = true; outrel.r_offset += (input_section->output_section->vma + input_section->output_offset); @@ -1509,6 +1499,47 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, } break; + case R_ARM_THM_PC11: + /* Thumb B (branch) instruction). */ + { + bfd_vma relocation; + bfd_signed_vma reloc_signed_max = (1 << (howto->bitsize - 1)) - 1; + bfd_signed_vma reloc_signed_min = ~ reloc_signed_max; + bfd_vma check; + bfd_signed_vma signed_check; + +#ifdef USE_REL + /* Need to refetch addend. */ + addend = bfd_get_16 (input_bfd, hit_data) & howto->src_mask; + /* ??? Need to determine shift amount from operand size. */ + addend >>= howto->rightshift; +#endif + relocation = value + addend; + + relocation -= (input_section->output_section->vma + + input_section->output_offset + + rel->r_offset); + + check = relocation >> howto->rightshift; + + /* If this is a signed value, the rightshift just + dropped leading 1 bits (assuming twos complement). */ + if ((bfd_signed_vma) relocation >= 0) + signed_check = check; + else + signed_check = check | ~((bfd_vma) -1 >> howto->rightshift); + + relocation |= (bfd_get_16 (input_bfd, hit_data) & (~ howto->dst_mask)); + + bfd_put_16 (input_bfd, relocation, hit_data); + + /* Assumes two's complement. */ + if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) + return bfd_reloc_overflow; + + return bfd_reloc_ok; + } + case R_ARM_GNU_VTINHERIT: case R_ARM_GNU_VTENTRY: return bfd_reloc_ok; @@ -1857,9 +1888,49 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section, { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; +#ifdef USE_REL relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); + if ((sec->flags & SEC_MERGE) + && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + asection *msec; + bfd_vma addend, value; + + if (howto->rightshift) + { + (*_bfd_error_handler) + (_("%s(%s+0x%lx): %s relocation against SEC_MERGE section"), + bfd_archive_filename (input_bfd), + bfd_get_section_name (input_bfd, input_section), + (long) rel->r_offset, howto->name); + return false; + } + + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + + /* Get the (signed) value from the instruction. */ + addend = value & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~ howto->src_mask; + addend |= mask; + } + msec = sec; + addend = + _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) + - relocation; + addend += msec->output_section->vma + msec->output_offset; + value = (value & ~ howto->dst_mask) | (addend & howto->dst_mask); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + } +#else + relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel); +#endif } else { @@ -1883,6 +1954,7 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section, { case R_ARM_PC24: case R_ARM_ABS32: + case R_ARM_THM_PC22: if (info->shared && ( (!info->symbolic && h->dynindx != -1) @@ -1923,8 +1995,10 @@ elf32_arm_relocate_section (output_bfd, info, input_bfd, input_section, if (sec->output_section == NULL) { (*_bfd_error_handler) - (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), - bfd_archive_filename (input_bfd), h->root.root.string, + (_("%s: warning: unresolvable relocation %d against symbol `%s' from %s section"), + bfd_archive_filename (input_bfd), + r_type, + h->root.root.string, bfd_get_section_name (input_bfd, input_section)); relocation_needed = 0; } @@ -2038,12 +2112,12 @@ elf32_arm_set_private_flags (abfd, flags) { if (flags & EF_ARM_INTERWORK) (*_bfd_error_handler) (_("\ -Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"), +Warning: Not setting interworking flag of %s since it has already been specified as non-interworking"), bfd_archive_filename (abfd)); else - (*_bfd_error_handler) (_("\ -Warning: Clearing the interwork flag of %s due to outside request"), - bfd_archive_filename (abfd)); + _bfd_error_handler (_("\ +Warning: Clearing the interworking flag of %s due to outside request"), + bfd_archive_filename (abfd)); } } else @@ -2089,12 +2163,10 @@ elf32_arm_copy_private_bfd_data (ibfd, obfd) if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) { if (out_flags & EF_ARM_INTERWORK) - { - (*_bfd_error_handler) (_("\ -Warning: Clearing the interwork flag in %s because non-interworking code in %s has been linked with it"), - bfd_get_filename (obfd), - bfd_archive_filename (ibfd)); - } + _bfd_error_handler (_("\ +Warning: Clearing the interworking flag of %s because non-interworking code in %s has been linked with it"), + bfd_get_filename (obfd), + bfd_archive_filename (ibfd)); in_flags &= ~EF_ARM_INTERWORK; } @@ -2186,12 +2258,12 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd) /* Complain about various flag mismatches. */ if (EF_ARM_EABI_VERSION (in_flags) != EF_ARM_EABI_VERSION (out_flags)) { - (*_bfd_error_handler) (_("\ -Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"), - bfd_archive_filename (ibfd), - (in_flags & EF_ARM_EABIMASK) >> 24, - bfd_get_filename (obfd), - (out_flags & EF_ARM_EABIMASK) >> 24); + _bfd_error_handler (_("\ +ERROR: %s is compiled for EABI version %d, whereas %s is compiled for version %d"), + bfd_archive_filename (ibfd), + (in_flags & EF_ARM_EABIMASK) >> 24, + bfd_get_filename (obfd), + (out_flags & EF_ARM_EABIMASK) >> 24); return false; } @@ -2200,51 +2272,94 @@ Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"), { if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26)) { - (*_bfd_error_handler) (_("\ -Error: %s compiled for APCS-%d, whereas %s is compiled for APCS-%d"), - bfd_archive_filename (ibfd), - in_flags & EF_ARM_APCS_26 ? 26 : 32, - bfd_get_filename (obfd), - out_flags & EF_ARM_APCS_26 ? 26 : 32); + _bfd_error_handler (_("\ +ERROR: %s is compiled for APCS-%d, whereas target %s uses APCS-%d"), + bfd_archive_filename (ibfd), + in_flags & EF_ARM_APCS_26 ? 26 : 32, + bfd_get_filename (obfd), + out_flags & EF_ARM_APCS_26 ? 26 : 32); flags_compatible = false; } if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT)) { - char *s1 = in_flags & EF_ARM_APCS_FLOAT ? _("float") : _("integer"); - char *s2 = out_flags & EF_ARM_APCS_26 ? _("float") : _("integer"); - (*_bfd_error_handler) (_("\ -Error: %s passes floats in %s registers, whereas %s passes them in %s registers"), - bfd_archive_filename (ibfd), s1, - bfd_get_filename (obfd), s2); + if (in_flags & EF_ARM_APCS_FLOAT) + _bfd_error_handler (_("\ +ERROR: %s passes floats in float registers, whereas %s passes them in integer registers"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + else + _bfd_error_handler (_("\ +ERROR: %s passes floats in integer registers, whereas %s passes them in float registers"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + + flags_compatible = false; + } + + if ((in_flags & EF_ARM_VFP_FLOAT) != (out_flags & EF_ARM_VFP_FLOAT)) + { + if (in_flags & EF_ARM_VFP_FLOAT) + _bfd_error_handler (_("\ +ERROR: %s uses VFP instructions, whereas %s uses FPA instructions"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + else + _bfd_error_handler (_("\ +ERROR: %s uses FPA instructions, whereas %s uses VFP instructions"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + flags_compatible = false; } #ifdef EF_ARM_SOFT_FLOAT if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT)) { - char *s1 = in_flags & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard"); - char *s2 = out_flags & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard"); - (*_bfd_error_handler) (_ ("\ -Error: %s uses %s floating point, whereas %s uses %s floating point"), - bfd_archive_filename (ibfd), s1, - bfd_get_filename (obfd), s2); - flags_compatible = false; + /* We can allow interworking between code that is VFP format + layout, and uses either soft float or integer regs for + passing floating point arguments and results. We already + know that the APCS_FLOAT flags match; similarly for VFP + flags. */ + if ((in_flags & EF_ARM_APCS_FLOAT) != 0 + || (in_flags & EF_ARM_VFP_FLOAT) == 0) + { + if (in_flags & EF_ARM_SOFT_FLOAT) + _bfd_error_handler (_("\ +ERROR: %s uses software FP, whereas %s uses hardware FP"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + else + _bfd_error_handler (_("\ +ERROR: %s uses hardware FP, whereas %s uses software FP"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + + flags_compatible = false; + } } #endif /* Interworking mismatch is only a warning. */ if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) { - char *s1 = (in_flags & EF_ARM_INTERWORK - ? _("supports") : _("does not support")); - char *s2 = out_flags & EF_ARM_INTERWORK ? _("does") : _("does not"); - (*_bfd_error_handler) (_("\ -Warning: %s %s interworking, whereas %s %s"), - bfd_archive_filename (ibfd), s1, - bfd_get_filename (obfd), s2); + if (in_flags & EF_ARM_INTERWORK) + { + _bfd_error_handler (_("\ +Warning: %s supports interworking, whereas %s does not"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + } + else + { + _bfd_error_handler (_("\ +Warning: %s does not support interworking, whereas %s does"), + bfd_archive_filename (ibfd), + bfd_get_filename (obfd)); + } } } + return flags_compatible; } @@ -2280,9 +2395,14 @@ elf32_arm_print_private_bfd_data (abfd, ptr) fprintf (file, _(" [interworking enabled]")); if (flags & EF_ARM_APCS_26) - fprintf (file, _(" [APCS-26]")); + fprintf (file, " [APCS-26]"); + else + fprintf (file, " [APCS-32]"); + + if (flags & EF_ARM_VFP_FLOAT) + fprintf (file, _(" [VFP float format]")); else - fprintf (file, _(" [APCS-32]")); + fprintf (file, _(" [FPA float format]")); if (flags & EF_ARM_APCS_FLOAT) fprintf (file, _(" [floats passed in float registers]")); @@ -2299,8 +2419,9 @@ elf32_arm_print_private_bfd_data (abfd, ptr) if (flags & EF_ARM_SOFT_FLOAT) fprintf (file, _(" [software FP]")); - flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT | EF_ARM_PIC - | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI | EF_ARM_SOFT_FLOAT); + flags &= ~(EF_ARM_INTERWORK | EF_ARM_APCS_26 | EF_ARM_APCS_FLOAT + | EF_ARM_PIC | EF_ARM_NEW_ABI | EF_ARM_OLD_ABI + | EF_ARM_SOFT_FLOAT | EF_ARM_VFP_FLOAT); break; case EF_ARM_EABI_VER1: @@ -2414,14 +2535,9 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym) } 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 bfd_section_from_elf_index (abfd, sym->st_shndx); + } + return NULL; } @@ -2557,7 +2673,7 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) if (local_got_offsets == NULL) { bfd_size_type size; - register unsigned int i; + unsigned int i; size = symtab_hdr->sh_info; size *= sizeof (bfd_vma); @@ -3085,12 +3201,16 @@ elf32_arm_size_dynamic_sections (output_bfd, info) asection ** spp; for (spp = &s->output_section->owner->sections; - *spp != s->output_section; + *spp != NULL; spp = &(*spp)->next) - ; - *spp = s->output_section->next; - --s->output_section->owner->section_count; - + { + if (*spp == s->output_section) + { + bfd_section_list_remove (s->output_section->owner, spp); + --s->output_section->owner->section_count; + break; + } + } continue; } @@ -3459,10 +3579,10 @@ elf32_arm_post_process_headers (abfd, link_info) } static enum elf_reloc_type_class -elf32_arm_reloc_type_class (type) - int type; +elf32_arm_reloc_type_class (rela) + const Elf_Internal_Rela *rela; { - switch (type) + switch ((int) ELF32_R_TYPE (rela->r_info)) { case R_ARM_RELATIVE: return reloc_class_relative;