diff options
Diffstat (limited to 'contrib/binutils/bfd/elf32-arm.h')
-rw-r--r-- | contrib/binutils/bfd/elf32-arm.h | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/contrib/binutils/bfd/elf32-arm.h b/contrib/binutils/bfd/elf32-arm.h index 0f2ac8a..66edd6d 100644 --- a/contrib/binutils/bfd/elf32-arm.h +++ b/contrib/binutils/bfd/elf32-arm.h @@ -1,5 +1,5 @@ /* 32-bit ELF support for ARM - Copyright 1998, 1999, 2000 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -78,22 +78,22 @@ static int elf32_thumb_to_arm_stub 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 bfd_byte elf32_arm_plt0_entry [PLT_ENTRY_SIZE] = +static const unsigned long elf32_arm_plt0_entry [PLT_ENTRY_SIZE / 4] = { - 0x04, 0xe0, 0x2d, 0xe5, /* str lr, [sp, #-4]! */ - 0x10, 0xe0, 0x9f, 0xe5, /* ldr lr, [pc, #16] */ - 0x0e, 0xe0, 0x8f, 0xe0, /* adr lr, pc, lr */ - 0x08, 0xf0, 0xbe, 0xe5 /* ldr pc, [lr, #8]! */ + 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 bfd_byte elf32_arm_plt_entry [PLT_ENTRY_SIZE] = +static const unsigned long elf32_arm_plt_entry [PLT_ENTRY_SIZE / 4] = { - 0x04, 0xc0, 0x9f, 0xe5, /* ldr ip, [pc, #4] */ - 0x0c, 0xc0, 0x8f, 0xe0, /* add ip, pc, ip */ - 0x00, 0xf0, 0x9c, 0xe5, /* ldr pc, [ip] */ - 0x00, 0x00, 0x00, 0x00 /* offset to symbol in got */ + 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 @@ -1019,6 +1019,18 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, bfd_signed_vma signed_addend; struct elf32_arm_link_hash_table * globals; + /* If the start address has been set, then set the EF_ARM_HASENTRY + flag. Setting this more than once is redundant, but the cost is + not too high, and it keeps the code simple. + + The test is done here, rather than somewhere else, because the + start address is only set just before the final link commences. + + Note - if the user deliberately sets a start address of 0, the + flag will not be set. */ + if (bfd_get_start_address (output_bfd) != 0) + elf_elfheader (output_bfd)->e_flags |= EF_ARM_HASENTRY; + globals = elf32_arm_hash_table (info); dynobj = elf_hash_table (info)->dynobj; @@ -1434,6 +1446,18 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, 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; +#endif /* 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); @@ -3135,9 +3159,12 @@ elf32_arm_finish_dynamic_symbol (output_bfd, info, h, sym) got_offset = (plt_index + 3) * 4; /* Fill in the entry in the procedure linkage table. */ - memcpy (splt->contents + h->plt.offset, - elf32_arm_plt_entry, - PLT_ENTRY_SIZE); + bfd_put_32 (output_bfd, elf32_arm_plt_entry[0], + splt->contents + h->plt.offset + 0); + bfd_put_32 (output_bfd, elf32_arm_plt_entry[1], + splt->contents + h->plt.offset + 4); + bfd_put_32 (output_bfd, elf32_arm_plt_entry[2], + splt->contents + h->plt.offset + 8); bfd_put_32 (output_bfd, (sgot->output_section->vma + sgot->output_offset @@ -3333,7 +3360,12 @@ elf32_arm_finish_dynamic_sections (output_bfd, info) /* Fill in the first entry in the procedure linkage table. */ if (splt->_raw_size > 0) - memcpy (splt->contents, elf32_arm_plt0_entry, PLT_ENTRY_SIZE); + { + bfd_put_32 (output_bfd, elf32_arm_plt0_entry[0], splt->contents + 0); + bfd_put_32 (output_bfd, elf32_arm_plt0_entry[1], splt->contents + 4); + bfd_put_32 (output_bfd, elf32_arm_plt0_entry[2], splt->contents + 8); + bfd_put_32 (output_bfd, elf32_arm_plt0_entry[3], splt->contents + 12); + } /* UnixWare sets the entsize of .plt to 4, although that doesn't really seem like the right value. */ |