diff options
Diffstat (limited to 'contrib/binutils/bfd/elf32-arm.h')
-rw-r--r-- | contrib/binutils/bfd/elf32-arm.h | 172 |
1 files changed, 87 insertions, 85 deletions
diff --git a/contrib/binutils/bfd/elf32-arm.h b/contrib/binutils/bfd/elf32-arm.h index 7d02127..f41b843 100644 --- a/contrib/binutils/bfd/elf32-arm.h +++ b/contrib/binutils/bfd/elf32-arm.h @@ -58,7 +58,7 @@ static boolean elf32_arm_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **)); static asection * elf32_arm_gc_mark_hook - PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, + PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *)); static boolean elf32_arm_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, @@ -236,14 +236,14 @@ elf32_arm_link_hash_table_create (abfd) struct elf32_arm_link_hash_table *ret; bfd_size_type amt = sizeof (struct elf32_arm_link_hash_table); - ret = (struct elf32_arm_link_hash_table *) bfd_alloc (abfd, amt); + ret = (struct elf32_arm_link_hash_table *) bfd_malloc (amt); 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); + free (ret); return NULL; } @@ -547,31 +547,22 @@ record_thumb_to_arm_glue (link_info, h) return; } -/* Select a BFD to be used to hold the sections used by the glue code. - This function is called from the linker scripts in ld/emultempl/ - {armelf/pe}.em */ +/* Add the glue sections to ABFD. This function is called from the + linker scripts in ld/emultempl/{armelf}.em. */ boolean -bfd_elf32_arm_get_bfd_for_interworking (abfd, info) +bfd_elf32_arm_add_glue_sections_to_bfd (abfd, info) bfd *abfd; struct bfd_link_info *info; { - struct elf32_arm_link_hash_table *globals; flagword flags; asection *sec; - /* If we are only performing a partial link do not bother - getting a bfd to hold the glue. */ + /* If we are only performing a partial + link do not bother adding the glue. */ if (info->relocateable) return true; - globals = elf32_arm_hash_table (info); - - BFD_ASSERT (globals != NULL); - - if (globals->bfd_of_glue_owner != NULL) - return true; - sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME); if (sec == NULL) @@ -609,6 +600,32 @@ bfd_elf32_arm_get_bfd_for_interworking (abfd, info) sec->gc_mark = 1; } + return true; +} + +/* Select a BFD to be used to hold the sections used by the glue code. + This function is called from the linker scripts in ld/emultempl/ + {armelf/pe}.em */ + +boolean +bfd_elf32_arm_get_bfd_for_interworking (abfd, info) + bfd *abfd; + struct bfd_link_info *info; +{ + struct elf32_arm_link_hash_table *globals; + + /* If we are only performing a partial link + do not bother getting a bfd to hold the glue. */ + if (info->relocateable) + return true; + + globals = elf32_arm_hash_table (info); + + BFD_ASSERT (globals != NULL); + + if (globals->bfd_of_glue_owner != NULL) + return true; + /* Save the bfd for later use. */ globals->bfd_of_glue_owner = abfd; @@ -622,12 +639,9 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) int no_pipeline_knowledge; { Elf_Internal_Shdr *symtab_hdr; - Elf_Internal_Rela *free_relocs = NULL; + Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; - bfd_byte *free_contents = NULL; - Elf32_External_Sym *extsyms = NULL; - Elf32_External_Sym *free_extsyms = NULL; asection *sec; struct elf32_arm_link_hash_table *globals; @@ -660,13 +674,15 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Load the relocs. */ - irel = (_bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL, - (Elf_Internal_Rela *) NULL, false)); + internal_relocs + = _bfd_elf32_link_read_relocs (abfd, sec, (PTR) NULL, + (Elf_Internal_Rela *) NULL, false); - BFD_ASSERT (irel != 0); + if (internal_relocs == NULL) + goto error_return; - irelend = irel + sec->reloc_count; - for (; irel < irelend; irel++) + irelend = internal_relocs + sec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++) { long r_type; unsigned long r_index; @@ -694,37 +710,12 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) if (contents == NULL) goto error_return; - free_contents = contents; - if (!bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) goto error_return; } } - /* Read this BFD's symbols if we haven't done so already. */ - if (extsyms == NULL) - { - /* Get cached copy if it exists. */ - if (symtab_hdr->contents != NULL) - extsyms = (Elf32_External_Sym *) symtab_hdr->contents; - else - { - /* Go get them off disk. */ - extsyms = ((Elf32_External_Sym *) - bfd_malloc (symtab_hdr->sh_size)); - if (extsyms == NULL) - goto error_return; - - free_extsyms = extsyms; - - if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 - || (bfd_bread (extsyms, symtab_hdr->sh_size, abfd) - != symtab_hdr->sh_size)) - goto error_return; - } - } - /* If the relocation is not against a symbol it cannot concern us. */ h = NULL; @@ -764,17 +755,27 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) break; } } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + contents = NULL; + + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + internal_relocs = NULL; } return true; error_return: - if (free_relocs != NULL) - free (free_relocs); - if (free_contents != NULL) - free (free_contents); - if (free_extsyms != NULL) - free (free_extsyms); + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (internal_relocs != NULL + && elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); return false; } @@ -1471,22 +1472,19 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, if (signed_check > reloc_signed_max || signed_check < reloc_signed_min) overflow = true; - /* Put RELOCATION back into the insn. */ - upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); - lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); - #ifndef OLD_ARM_ABI if (r_type == R_ARM_THM_XPC22 && ((lower_insn & 0x1800) == 0x0800)) - /* Remove bit zero of the adjusted offset. Bit zero can only be - set if the upper insn is at a half-word boundary, since the - destination address, an ARM instruction, must always be on a - word boundary. The semantics of the BLX (1) instruction, however, - are that bit zero in the offset must always be zero, and the - corresponding bit one in the target address will be set from bit - one of the source address. */ - lower_insn &= ~1; + /* For a BLX instruction, make sure that the relocation is rounded up + to a word boundary. This follows the semantics of the instruction + which specifies that bit 1 of the target address will come from bit + 1 of the base address. */ + relocation = (relocation + 2) & ~ 3; #endif + /* Put RELOCATION back into the insn. */ + upper_insn = (upper_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 12) & 0x7ff); + lower_insn = (lower_insn & ~(bfd_vma) 0x7ff) | ((relocation >> 1) & 0x7ff); + /* Put the relocated value back in the object file: */ bfd_put_16 (input_bfd, upper_insn, hit_data); bfd_put_16 (input_bfd, lower_insn, hit_data + 2); @@ -1526,7 +1524,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, 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. */ @@ -1535,7 +1533,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, return bfd_reloc_ok; } - + case R_ARM_GNU_VTINHERIT: case R_ARM_GNU_VTENTRY: return bfd_reloc_ok; @@ -1560,7 +1558,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, if (sgot == NULL) return bfd_reloc_notsupported; - /* If we are addressing a Thumb function, we need to adjust the + /* If we are addressing a Thumb function, we need to adjust the address by one, so that attempts to call the function pointer will correctly interpret it as Thumb code. */ if (sym_flags == STT_ARM_TFUNC) @@ -2209,7 +2207,7 @@ elf32_arm_merge_private_bfd_data (ibfd, obfd) asection *sec; /* Check if we have the same endianess. */ - if (_bfd_generic_verify_endian_match (ibfd, obfd) == false) + if (! _bfd_generic_verify_endian_match (ibfd, obfd)) return false; if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour @@ -2360,7 +2358,7 @@ ERROR: %s uses hardware FP, whereas %s uses software FP"), _bfd_error_handler (_("\ Warning: %s supports interworking, whereas %s does not"), bfd_archive_filename (ibfd), - bfd_get_filename (obfd)); + bfd_get_filename (obfd)); } else { @@ -2515,8 +2513,8 @@ elf32_arm_get_symbol_type (elf_sym, type) } static asection * -elf32_arm_gc_mark_hook (abfd, info, rel, h, sym) - bfd *abfd; +elf32_arm_gc_mark_hook (sec, info, rel, h, sym) + asection *sec; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; @@ -2546,9 +2544,7 @@ elf32_arm_gc_mark_hook (abfd, info, rel, h, sym) } } else - { - return bfd_section_from_elf_index (abfd, sym->st_shndx); - } + return bfd_section_from_elf_index (sec->owner, sym->st_shndx); return NULL; } @@ -2962,16 +2958,22 @@ elf32_arm_adjust_dynamic_symbol (info, h) if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { + /* If we link a program (not a DSO), we'll get rid of unnecessary + PLT entries; we point to the actual symbols -- even for pic + relocs, because a program built with -fpic should have the same + result as one built without -fpic, specifically considering weak + symbols. + FIXME: m68k and i386 differ here, for unclear reasons. */ if (! info->shared - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_DYNAMIC) == 0) + && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) == 0) { /* This case can occur if we saw a PLT32 reloc in an input - file, but the symbol was never referred to by a dynamic - object. In such a case, we don't actually need to build - a procedure linkage table, and we can just do a PC32 - reloc instead. */ + file, but the symbol was not defined by a dynamic object. + In such a case, we don't actually need to build a + procedure linkage table, and we can just do a PC32 reloc + instead. */ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; return true; } |