X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=bfd%2Felf32-arm.h;h=f8f94d66b8351d3d27f68e69b3664e12534556f3;hb=563e308f244b1d6adb9d012a3e11d458400b3ff2;hp=7bd0cceab2b54aa39cd99312f0f34fad7ffc329b;hpb=cf919dfdd753416017c8a78dc7271e2a6f77465c;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arm.h b/bfd/elf32-arm.h index 7bd0cceab2..f8f94d66b8 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 Free Software Foundation, Inc. + Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -17,7 +17,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - typedef unsigned long int insn32; typedef unsigned short int insn16; @@ -56,7 +55,7 @@ static int elf32_thumb_to_arm_stub PARAMS ((struct bfd_link_info *, const char *, bfd *, bfd *, asection *, bfd_byte *, asection *, bfd_vma, bfd_signed_vma, bfd_vma)); -#define INTERWORK_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_INTERWORK) +#define INTERWORK_FLAG(abfd) (elf_elfheader (abfd)->e_flags & EF_ARM_INTERWORK) /* The linker script knows the section names for placement. The entry_names are used to do simple name mangling on the stubs. @@ -79,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 @@ -159,7 +158,6 @@ struct elf32_arm_link_hash_table int no_pipeline_knowledge; }; - /* Create an entry in an ARM ELF linker hash table. */ static struct bfd_hash_entry * @@ -682,7 +680,7 @@ bfd_elf32_arm_process_before_allocation (abfd, link_info, no_pipeline_knowledge) } } - /* If the relocation is not against a symbol it cannot concern us. */ + /* If the relocation is not against a symbol it cannot concern us. */ h = NULL; /* We don't care about local symbols. */ @@ -1021,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; @@ -1285,7 +1295,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, case R_ARM_REL32: value -= (input_section->output_section->vma - + input_section->output_offset); + + input_section->output_offset + rel->r_offset); value += addend; break; } @@ -1436,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); @@ -1479,7 +1501,7 @@ elf32_arm_final_link_relocate (howto, input_bfd, output_bfd, (bfd_vma) 0); case R_ARM_GOTPC: - /* Use global offset table as symbol value. */ + /* Use global offset table as symbol value. */ BFD_ASSERT (sgot != NULL); if (sgot == NULL) @@ -1965,7 +1987,7 @@ elf32_arm_set_private_flags (abfd, flags) { if (EF_ARM_EABI_VERSION (flags) == EF_ARM_EABI_UNKNOWN) { - if (flags & EF_INTERWORK) + if (flags & EF_ARM_INTERWORK) _bfd_error_handler (_("\ Warning: Not setting interwork flag of %s since it has already been specified as non-interworking"), bfd_get_filename (abfd)); @@ -2006,28 +2028,28 @@ elf32_arm_copy_private_bfd_data (ibfd, obfd) && in_flags != out_flags) { /* Cannot mix APCS26 and APCS32 code. */ - if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26)) + if ((in_flags & EF_ARM_APCS_26) != (out_flags & EF_ARM_APCS_26)) return false; /* Cannot mix float APCS and non-float APCS code. */ - if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT)) + if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT)) return false; /* If the src and dest have different interworking flags then turn off the interworking bit. */ - if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK)) + if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) { - if (out_flags & EF_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_get_filename (ibfd)); - in_flags &= ~EF_INTERWORK; + in_flags &= ~EF_ARM_INTERWORK; } /* Likewise for PIC, though don't warn for this case. */ - if ((in_flags & EF_PIC) != (out_flags & EF_PIC)) - in_flags &= ~EF_PIC; + if ((in_flags & EF_ARM_PIC) != (out_flags & EF_ARM_PIC)) + in_flags &= ~EF_ARM_PIC; } elf_elfheader (obfd)->e_flags = in_flags; @@ -2124,49 +2146,49 @@ Error: %s compiled for EABI version %d, whereas %s is compiled for version %d"), /* Not sure what needs to be checked for EABI versions >= 1. */ if (EF_ARM_EABI_VERSION (in_flags) == EF_ARM_EABI_UNKNOWN) { - if ((in_flags & EF_APCS_26) != (out_flags & EF_APCS_26)) + 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_get_filename (ibfd), - in_flags & EF_APCS_26 ? 26 : 32, + in_flags & EF_ARM_APCS_26 ? 26 : 32, bfd_get_filename (obfd), - out_flags & EF_APCS_26 ? 26 : 32); + out_flags & EF_ARM_APCS_26 ? 26 : 32); flags_compatible = false; } - if ((in_flags & EF_APCS_FLOAT) != (out_flags & EF_APCS_FLOAT)) + if ((in_flags & EF_ARM_APCS_FLOAT) != (out_flags & EF_ARM_APCS_FLOAT)) { _bfd_error_handler (_("\ Error: %s passes floats in %s registers, whereas %s passes them in %s registers"), bfd_get_filename (ibfd), - in_flags & EF_APCS_FLOAT ? _("float") : _("integer"), + in_flags & EF_ARM_APCS_FLOAT ? _("float") : _("integer"), bfd_get_filename (obfd), - out_flags & EF_APCS_26 ? _("float") : _("integer")); + out_flags & EF_ARM_APCS_26 ? _("float") : _("integer")); flags_compatible = false; } -#ifdef EF_SOFT_FLOAT - if ((in_flags & EF_SOFT_FLOAT) != (out_flags & EF_SOFT_FLOAT)) +#ifdef EF_ARM_SOFT_FLOAT + if ((in_flags & EF_ARM_SOFT_FLOAT) != (out_flags & EF_ARM_SOFT_FLOAT)) { _bfd_error_handler (_ ("\ Error: %s uses %s floating point, whereas %s uses %s floating point"), bfd_get_filename (ibfd), - in_flags & EF_SOFT_FLOAT ? _("soft") : _("hard"), + in_flags & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard"), bfd_get_filename (obfd), - out_flags & EF_SOFT_FLOAT ? _("soft") : _("hard")); + out_flags & EF_ARM_SOFT_FLOAT ? _("soft") : _("hard")); flags_compatible = false; } #endif /* Interworking mismatch is only a warning. */ - if ((in_flags & EF_INTERWORK) != (out_flags & EF_INTERWORK)) + if ((in_flags & EF_ARM_INTERWORK) != (out_flags & EF_ARM_INTERWORK)) _bfd_error_handler (_("\ Warning: %s %s interworking, whereas %s %s"), - bfd_get_filename (ibfd), - in_flags & EF_INTERWORK ? _("supports") : _("does not support"), - bfd_get_filename (obfd), - out_flags & EF_INTERWORK ? _("does not") : _("does")); + bfd_get_filename (ibfd), + in_flags & EF_ARM_INTERWORK ? _("supports") : _("does not support"), + bfd_get_filename (obfd), + out_flags & EF_ARM_INTERWORK ? _("does") : _("does not")); } return flags_compatible; @@ -2200,31 +2222,31 @@ elf32_arm_print_private_bfd_data (abfd, ptr) /* The following flag bits are GNU extenstions and not part of the official ARM ELF extended ABI. Hence they are only decoded if the EABI version is not set. */ - if (flags & EF_INTERWORK) + if (flags & EF_ARM_INTERWORK) fprintf (file, _(" [interworking enabled]")); - if (flags & EF_APCS_26) + if (flags & EF_ARM_APCS_26) fprintf (file, _(" [APCS-26]")); else fprintf (file, _(" [APCS-32]")); - if (flags & EF_APCS_FLOAT) + if (flags & EF_ARM_APCS_FLOAT) fprintf (file, _(" [floats passed in float registers]")); - if (flags & EF_PIC) + if (flags & EF_ARM_PIC) fprintf (file, _(" [position independent]")); - if (flags & EF_NEW_ABI) + if (flags & EF_ARM_NEW_ABI) fprintf (file, _(" [new ABI]")); - if (flags & EF_OLD_ABI) + if (flags & EF_ARM_OLD_ABI) fprintf (file, _(" [old ABI]")); - if (flags & EF_SOFT_FLOAT) + if (flags & EF_ARM_SOFT_FLOAT) fprintf (file, _(" [software FP]")); - flags &= ~(EF_INTERWORK | EF_APCS_26 | EF_APCS_FLOAT | EF_PIC - | EF_NEW_ABI | EF_OLD_ABI | EF_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); break; case EF_ARM_EABI_VER1: @@ -2238,6 +2260,24 @@ elf32_arm_print_private_bfd_data (abfd, ptr) flags &= ~ EF_ARM_SYMSARESORTED; break; + case EF_ARM_EABI_VER2: + fprintf (file, _(" [Version2 EABI]")); + + if (flags & EF_ARM_SYMSARESORTED) + fprintf (file, _(" [sorted symbol table]")); + else + fprintf (file, _(" [unsorted symbol table]")); + + if (flags & EF_ARM_DYNSYMSUSESEGIDX) + fprintf (file, _(" [dynamic symbols use segment index]")); + + if (flags & EF_ARM_MAPSYMSFIRST) + fprintf (file, _(" [mapping symbols precede others]")); + + flags &= ~(EF_ARM_SYMSARESORTED | EF_ARM_DYNSYMSUSESEGIDX + | EF_ARM_MAPSYMSFIRST); + break; + default: fprintf (file, _(" ")); break; @@ -2621,7 +2661,6 @@ elf32_arm_check_relocs (abfd, info, sec, relocs) return true; } - /* Find the nearest line to a particular section and offset, for error reporting. This code is a duplicate of the code in elf.c, except that it also accepts STT_ARM_TFUNC as a symbol that names a function. */ @@ -2645,7 +2684,8 @@ elf32_arm_find_nearest_line if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, filename_ptr, functionname_ptr, - line_ptr, 0)) + line_ptr, 0, + &elf_tdata (abfd)->dwarf2_find_line_info)) return true; if (! _bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, @@ -3137,9 +3177,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 @@ -3169,6 +3212,13 @@ elf32_arm_finish_dynamic_symbol (output_bfd, info, h, sym) /* Mark the symbol as undefined, rather than as defined in the .plt section. Leave the value alone. */ sym->st_shndx = SHN_UNDEF; + /* If the symbol is weak, we do need to clear the value. + Otherwise, the PLT entry would provide a definition for + the symbol even if the symbol wasn't defined anywhere, + and so the symbol would never be NULL. */ + if ((h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR_NONWEAK) + == 0) + sym->st_value = 0; } } @@ -3328,7 +3378,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. */ @@ -3366,12 +3421,10 @@ elf32_arm_post_process_headers (abfd, link_info) i_ehdrp->e_ident[EI_ABIVERSION] = ARM_ELF_ABI_VERSION; } - #define ELF_ARCH bfd_arch_arm #define ELF_MACHINE_CODE EM_ARM #define ELF_MAXPAGESIZE 0x8000 - #define bfd_elf32_bfd_copy_private_bfd_data elf32_arm_copy_private_bfd_data #define bfd_elf32_bfd_merge_private_bfd_data elf32_arm_merge_private_bfd_data #define bfd_elf32_bfd_set_private_flags elf32_arm_set_private_flags