? changelog-diffs Index: bfd/bfd-in2.h =================================================================== RCS file: /cvs/src/src/bfd/bfd-in2.h,v retrieving revision 1.446 diff -u -p -r1.446 bfd-in2.h --- bfd/bfd-in2.h 21 May 2008 12:01:36 -0000 1.446 +++ bfd/bfd-in2.h 1 Jul 2008 16:08:49 -0000 @@ -2661,7 +2661,7 @@ to compensate for the borrow when the lo BFD_RELOC_MIPS_TLS_TPREL_LO16, -/* MIPS ELF relocations (VxWorks extensions). */ +/* MIPS ELF relocations (VxWorks and nonpic extensions). */ BFD_RELOC_MIPS_COPY, BFD_RELOC_MIPS_JUMP_SLOT, Index: bfd/elf32-mips.c =================================================================== RCS file: /cvs/src/src/bfd/elf32-mips.c,v retrieving revision 1.197 diff -u -p -r1.197 elf32-mips.c --- bfd/elf32-mips.c 27 Feb 2008 17:06:06 -0000 1.197 +++ bfd/elf32-mips.c 1 Jul 2008 16:08:49 -0000 @@ -875,6 +875,36 @@ static reloc_howto_type elf_mips_gnu_vte 0, /* dst_mask */ FALSE); /* pcrel_offset */ +static reloc_howto_type elf_mips_copy_howto = + HOWTO (R_MIPS_COPY, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_COPY", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + +static reloc_howto_type elf_mips_jump_slot_howto = + HOWTO (R_MIPS_JUMP_SLOT, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_MIPS_JUMP_SLOT", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0, /* dst_mask */ + FALSE); /* pcrel_offset */ + /* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a dangerous relocation. */ @@ -1273,6 +1303,10 @@ bfd_elf32_bfd_reloc_type_lookup (bfd *ab return &elf_mips_gnu_vtentry_howto; case BFD_RELOC_32_PCREL: return &elf_mips_gnu_pcrel32; + case BFD_RELOC_MIPS_COPY: + return &elf_mips_copy_howto; + case BFD_RELOC_MIPS_JUMP_SLOT: + return &elf_mips_jump_slot_howto; } } @@ -1306,6 +1340,10 @@ bfd_elf32_bfd_reloc_name_lookup (bfd *ab return &elf_mips_gnu_vtinherit_howto; if (strcasecmp (elf_mips_gnu_vtentry_howto.name, r_name) == 0) return &elf_mips_gnu_vtentry_howto; + if (strcasecmp (elf_mips_copy_howto.name, r_name) == 0) + return &elf_mips_copy_howto; + if (strcasecmp (elf_mips_jump_slot_howto.name, r_name) == 0) + return &elf_mips_jump_slot_howto; return NULL; } @@ -1326,6 +1364,10 @@ mips_elf32_rtype_to_howto (unsigned int return &elf_mips_gnu_rel16_s2; case R_MIPS_PC32: return &elf_mips_gnu_pcrel32; + case R_MIPS_COPY: + return &elf_mips_copy_howto; + case R_MIPS_JUMP_SLOT: + return &elf_mips_jump_slot_howto; default: if (r_type >= R_MIPS16_min && r_type < R_MIPS16_max) return &elf_mips16_howto_table_rel[r_type - R_MIPS16_min]; @@ -1591,9 +1633,19 @@ static const struct ecoff_debug_swap mip #define elf_backend_default_use_rela_p 0 #define elf_backend_sign_extend_vma TRUE +/* Most MIPS ELF files do not contain a traditional PLT; only VxWorks + and non-PIC dynamic executables do. These settings only affect + _bfd_elf_create_dynamic_sections, which is only called when we + do want a traditional PLT. */ +#undef elf_backend_want_plt_sym +#define elf_backend_want_plt_sym 1 +#undef elf_backend_plt_readonly +#define elf_backend_plt_readonly 1 + #define elf_backend_discard_info _bfd_mips_elf_discard_info #define elf_backend_ignore_discarded_relocs \ _bfd_mips_elf_ignore_discarded_relocs +#define elf_backend_write_section _bfd_mips_elf_write_section #define elf_backend_mips_irix_compat elf32_mips_irix_compat #define elf_backend_mips_rtype_to_howto mips_elf32_rtype_to_howto #define bfd_elf32_bfd_is_local_label_name \ @@ -1613,6 +1665,8 @@ static const struct ecoff_debug_swap mip #define bfd_elf32_bfd_print_private_bfd_data \ _bfd_mips_elf_print_private_bfd_data +#define elf_backend_plt_sym_val _bfd_mips_elf_plt_sym_val + /* Support for SGI-ish mips targets. */ #define TARGET_LITTLE_SYM bfd_elf32_littlemips_vec #define TARGET_LITTLE_NAME "elf32-littlemips" @@ -1652,82 +1706,6 @@ static const struct ecoff_debug_swap mip /* Include the target file again for this target. */ #include "elf32-target.h" - -/* Specific to VxWorks. */ -static reloc_howto_type mips_vxworks_copy_howto_rela = - HOWTO (R_MIPS_COPY, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_MIPS_COPY", /* name */ - FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ - FALSE); /* pcrel_offset */ - -/* Specific to VxWorks. */ -static reloc_howto_type mips_vxworks_jump_slot_howto_rela = - HOWTO (R_MIPS_JUMP_SLOT, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_bitfield, /* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_MIPS_JUMP_SLOT", /* name */ - FALSE, /* partial_inplace */ - 0x0, /* src_mask */ - 0x0, /* dst_mask */ - FALSE); /* pcrel_offset */ - -/* Implement elf_backend_bfd_reloc_type_lookup for VxWorks. */ - -static reloc_howto_type * -mips_vxworks_bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code) -{ - switch (code) - { - case BFD_RELOC_MIPS_COPY: - return &mips_vxworks_copy_howto_rela; - case BFD_RELOC_MIPS_JUMP_SLOT: - return &mips_vxworks_jump_slot_howto_rela; - default: - return bfd_elf32_bfd_reloc_type_lookup (abfd, code); - } -} - -static reloc_howto_type * -mips_vxworks_bfd_reloc_name_lookup (bfd *abfd, const char *r_name) -{ - if (strcasecmp (mips_vxworks_copy_howto_rela.name, r_name) == 0) - return &mips_vxworks_copy_howto_rela; - if (strcasecmp (mips_vxworks_jump_slot_howto_rela.name, r_name) == 0) - return &mips_vxworks_jump_slot_howto_rela; - - return bfd_elf32_bfd_reloc_name_lookup (abfd, r_name); -} - -/* Implement elf_backend_mips_rtype_to_lookup for VxWorks. */ - -static reloc_howto_type * -mips_vxworks_rtype_to_howto (unsigned int r_type, bfd_boolean rela_p) -{ - switch (r_type) - { - case R_MIPS_COPY: - return &mips_vxworks_copy_howto_rela; - case R_MIPS_JUMP_SLOT: - return &mips_vxworks_jump_slot_howto_rela; - default: - return mips_elf32_rtype_to_howto (r_type, rela_p); - } -} - /* Implement elf_backend_final_write_processing for VxWorks. */ static void @@ -1758,12 +1736,6 @@ mips_vxworks_final_write_processing (bfd #undef elf_backend_want_got_plt #define elf_backend_want_got_plt 1 -#undef elf_backend_want_plt_sym -#define elf_backend_want_plt_sym 1 -#undef elf_backend_got_symbol_offset -#define elf_backend_got_symbol_offset 0 -#undef elf_backend_want_dynbss -#define elf_backend_want_dynbss 1 #undef elf_backend_may_use_rel_p #define elf_backend_may_use_rel_p 0 #undef elf_backend_may_use_rela_p @@ -1772,21 +1744,10 @@ mips_vxworks_final_write_processing (bfd #define elf_backend_default_use_rela_p 1 #undef elf_backend_got_header_size #define elf_backend_got_header_size (4 * 3) -#undef elf_backend_plt_readonly -#define elf_backend_plt_readonly 1 -#undef bfd_elf32_bfd_reloc_type_lookup -#define bfd_elf32_bfd_reloc_type_lookup \ - mips_vxworks_bfd_reloc_type_lookup -#undef bfd_elf32_bfd_reloc_name_lookup -#define bfd_elf32_bfd_reloc_name_lookup \ - mips_vxworks_bfd_reloc_name_lookup -#undef elf_backend_mips_rtype_to_howto -#define elf_backend_mips_rtype_to_howto \ - mips_vxworks_rtype_to_howto #undef elf_backend_adjust_dynamic_symbol #define elf_backend_adjust_dynamic_symbol \ - _bfd_mips_vxworks_adjust_dynamic_symbol + _bfd_mips_plt_adjust_dynamic_symbol #undef elf_backend_finish_dynamic_symbol #define elf_backend_finish_dynamic_symbol \ _bfd_mips_vxworks_finish_dynamic_symbol @@ -1809,6 +1770,7 @@ mips_vxworks_final_write_processing (bfd #undef elf_backend_additional_program_headers #undef elf_backend_modify_segment_map #undef elf_backend_symbol_processing +#undef elf_backend_plt_sym_val /* NOTE: elf_backend_rela_normal is not defined for MIPS. */ #include "elf32-target.h" Index: bfd/elflink.c =================================================================== RCS file: /cvs/src/src/bfd/elflink.c,v retrieving revision 1.304 diff -u -p -r1.304 elflink.c --- bfd/elflink.c 29 Apr 2008 11:53:45 -0000 1.304 +++ bfd/elflink.c 1 Jul 2008 16:08:49 -0000 @@ -1178,7 +1178,7 @@ _bfd_elf_merge_symbol (bfd *abfd, if (olddef && newdyn) oldweak = FALSE; - /* Allow changes between different types of funciton symbol. */ + /* Allow changes between different types of function symbol. */ if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)) && bed->is_function_type (h->type)) *type_change_ok = TRUE; Index: bfd/elfxx-mips.c =================================================================== RCS file: /cvs/src/src/bfd/elfxx-mips.c,v retrieving revision 1.230 diff -u -p -r1.230 elfxx-mips.c --- bfd/elfxx-mips.c 21 Apr 2008 17:54:24 -0000 1.230 +++ bfd/elfxx-mips.c 1 Jul 2008 16:08:50 -0000 @@ -306,9 +306,6 @@ struct mips_elf_link_hash_entry the initial global GOT entry to a local GOT entry. */ bfd_boolean forced_local; - /* Are we referenced by some kind of relocation? */ - bfd_boolean is_relocation_target; - /* Are we referenced by branch relocations? */ bfd_boolean is_branch_target; @@ -326,6 +323,18 @@ struct mips_elf_link_hash_entry possible to use root.got.offset instead, but that field is overloaded already. */ bfd_vma tls_got_offset; + + /* Offset of any corresponding PLT entry from the start of .plt + when using the non-PIC ABI, unless has_non_pic_to_pic_stub is + set, in which case it is the offset of the stub from the start + of the stubs section. */ + bfd_vma plt_entry_offset; + + /* Set if this symbol has a non-PIC -> PIC call stub associated + with it. If set, the PLT offset field specifies the offset into + the PLT section where the stub lies. All calls from non-PIC code + to the symbol must go via that stub. */ + bfd_boolean has_non_pic_to_pic_stub; }; /* MIPS ELF linker hash table. */ @@ -353,6 +362,10 @@ struct mips_elf_link_hash_table bfd_boolean computed_got_sizes; /* True if we're generating code for VxWorks. */ bfd_boolean is_vxworks; + /* True if we're generating code for the non-PIC ABI. */ + bfd_boolean is_non_pic; + /* A non-PIC input BFD with relocations, to attach stubs to. */ + bfd *non_pic_bfd; /* True if we already reported the small-data section overflow. */ bfd_boolean small_data_overflow_reported; /* Shortcuts to some dynamic sections, or NULL if they are not @@ -363,10 +376,13 @@ struct mips_elf_link_hash_table asection *srelplt2; asection *sgotplt; asection *splt; - /* The size of the PLT header in bytes (VxWorks only). */ + asection *snonpictopic; + /* The size of the PLT header in bytes (VxWorks and non-PIC ABI only). */ bfd_vma plt_header_size; - /* The size of a PLT entry in bytes (VxWorks only). */ + /* The size of a PLT entry in bytes (VxWorks and non-PIC ABI only). */ bfd_vma plt_entry_size; + /* The size of a large PLT entry in bytes (non-PIC ABI only). */ + bfd_vma large_plt_entry_size; /* The size of a function stub entry in bytes. */ bfd_vma function_stub_size; }; @@ -552,6 +568,11 @@ static bfd *reldyn_sorting_bfd; /* Nonzero if ABFD is using NewABI conventions. */ #define NEWABI_P(abfd) (ABI_N32_P (abfd) || ABI_64_P (abfd)) +/* Nonzero if ABFD is a non-PIC object. */ +#define NON_PIC_P(abfd) \ + (((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) == 0) \ + && ((elf_elfheader (abfd)->e_flags & EF_MIPS_CPIC) == EF_MIPS_CPIC)) + /* The IRIX compatibility level we are striving for. */ #define IRIX_COMPAT(abfd) \ (get_elf_backend_data (abfd)->elf_backend_mips_irix_compat (abfd)) @@ -564,6 +585,9 @@ static bfd *reldyn_sorting_bfd; #define MIPS_ELF_OPTIONS_SECTION_NAME(abfd) \ (NEWABI_P (abfd) ? ".MIPS.options" : ".options") +/* The name of the section holding non-PIC to PIC call stubs. */ +#define NON_PIC_TO_PIC_STUB_SECTION_NAME ".MIPS.pic_stubs" + /* True if NAME is the recognized name of any SHT_MIPS_OPTIONS section. Some IRIX system files do not use MIPS_ELF_OPTIONS_SECTION_NAME. */ #define MIPS_ELF_OPTIONS_SECTION_NAME_P(NAME) \ @@ -752,6 +776,56 @@ static bfd *reldyn_sorting_bfd; #define CALL_STUB_P(name) CONST_STRNEQ (name, CALL_STUB) #define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB) +#define MIPS_NONPIC_LARGE_PLT_THRESHOLD 65536 + +/* The format of the first PLT entry in a non-PIC ABI executable. + This branches to the dynamic linker to resolve a symbol. + This first PLT entry is called via one of the other PLT entries, + which will have initialised t8 to the PLT entry index. */ +static const bfd_vma mips_non_pic_exec_plt0_entry[] = { + 0x3c1c0000, /* lui $gp, */ + 0x279c0000, /* addiu $gp, */ + 0x8f990000, /* lw $t9, 0($gp) */ + 0x03e07821, /* move $t7, $ra */ + 0x0320f809, /* jalr $t9 */ + 0x00000000, /* nop */ + 0x00000000, /* nop */ + 0x00000000 /* nop */ +}; + +/* The format of subsequent PLT entries in a non-PIC ABI executable + whose (0-based) PLT indexes are less than + MIPS_NONPIC_LARGE_PLT_THRESHOLD. (One PLT may contain both entries + in this format and in the format of mips_non_pic_large_exec_plt_entry.) */ +static const bfd_vma mips_non_pic_exec_plt_entry[] = { + 0x3c0f0000, /* lui $t7, */ + 0x8df90000, /* lw $t9, ($t7) */ + 0x34180000, /* ori $t8, $0, */ + 0x03200008 /* jr $t9 */ +}; + +/* The format of subsequent PLT entries in a non-PIC ABI executable + whose (0-based) PLT indexes are greater than or equal to + MIPS_NONPIC_LARGE_PLT_THRESHOLD. */ +static const bfd_vma mips_non_pic_large_exec_plt_entry[] = { + 0x3c0f0000, /* lui $t7, */ + 0x8df90000, /* lw $t9, ($t7) */ + 0x3c180000, /* lui $t8, */ + 0x03200008, /* jr $t9 */ + 0x37180000, /* ori $t8, $t8, */ + 0x00000000, /* nop */ + 0x00000000, /* nop */ + 0x00000000 /* nop */ +}; + +/* The format of a stub used to call PIC code from non-PIC code. */ +static const bfd_vma mips_non_pic_to_pic_stub[] = { + 0x3c190000, /* lui $t9, */ + 0x27390000, /* addiu $t9, $t9, */ + 0x03200008, /* jr $t9 */ + 0x00000000 /* nop */ +}; + /* The format of the first PLT entry in a VxWorks executable. */ static const bfd_vma mips_vxworks_exec_plt0_entry[] = { 0x3c190000, /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_) */ @@ -870,8 +944,9 @@ mips_elf_link_hash_newfunc (struct bfd_h ret->call_fp_stub = NULL; ret->forced_local = FALSE; ret->is_branch_target = FALSE; - ret->is_relocation_target = FALSE; ret->tls_type = GOT_NORMAL; + ret->has_non_pic_to_pic_stub = FALSE; + ret->plt_entry_offset = (bfd_vma) -1; } return (struct bfd_hash_entry *) ret; @@ -4041,17 +4116,6 @@ mips_elf_create_got_section (bfd *abfd, mips_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL; - /* VxWorks also needs a .got.plt section. */ - if (htab->is_vxworks) - { - s = bfd_make_section_with_flags (abfd, ".got.plt", - SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS - | SEC_IN_MEMORY | SEC_LINKER_CREATED); - if (s == NULL || !bfd_set_section_alignment (abfd, s, 4)) - return FALSE; - - htab->sgotplt = s; - } return TRUE; } @@ -4293,8 +4357,16 @@ mips_elf_calculate_relocation (bfd *abfd /* If this is a 32- or 64-bit call to a 16-bit function with a stub, we need to redirect the call to the stub, unless we're already *in* - a stub. */ - if (r_type != R_MIPS16_26 && !info->relocatable + a stub. Likewise for non-PIC to PIC call stubs. (Note that + these latter varieties of stubs never contain any relocations, so + we don't need to check if we're within a stub section here.) */ + if (h != NULL && htab->is_non_pic + && (r_type == R_MIPS_26 || r_type == R_MIPS_PC16) + && h->has_non_pic_to_pic_stub) + symbol = htab->snonpictopic->output_section->vma + + htab->snonpictopic->output_section->output_offset + + h->plt_entry_offset; + else if (r_type != R_MIPS16_26 && !info->relocatable && ((h != NULL && h->fn_stub != NULL) || (local_p && elf_tdata (input_bfd)->local_stubs != NULL @@ -4357,6 +4429,17 @@ mips_elf_calculate_relocation (bfd *abfd BFD_ASSERT (sec->size > 0); symbol = sec->output_section->vma + sec->output_offset; } + else if (htab->is_non_pic && h != NULL + && !h->has_non_pic_to_pic_stub + && h->plt_entry_offset != (bfd_vma) -1) + { + BFD_ASSERT (!local_p); + BFD_ASSERT (r_type == R_MIPS_PC16 || addend == 0); + sec = htab->splt; + BFD_ASSERT (sec != NULL); + symbol = sec->output_section->vma + sec->output_offset + + h->plt_entry_offset; + } /* Calls from 16-bit code to 32-bit code and vice versa require the special jalx instruction. */ @@ -4516,8 +4599,9 @@ mips_elf_calculate_relocation (bfd *abfd case R_MIPS_64: if ((info->shared || (!htab->is_vxworks - && htab->root.dynamic_sections_created + && !htab->is_non_pic && h != NULL + && htab->root.dynamic_sections_created && h->root.def_dynamic && !h->root.def_regular)) && r_symndx != 0 @@ -4531,7 +4615,8 @@ mips_elf_calculate_relocation (bfd *abfd In VxWorks executables, references to external symbols are handled using copy relocs or PLT stubs, so there's - no need to add a dynamic relocation here. */ + no need to add a dynamic relocation here. Likewise for + the non-PIC ABI. */ value = addend; if (!mips_elf_create_dynamic_relocation (abfd, info, @@ -6150,6 +6235,56 @@ _bfd_mips_elf_link_output_symbol_hook /* Functions for the dynamic linker. */ +static bfd_boolean +_bfd_mips_elf_create_nonpic_dynamic_sections (bfd *abfd, + struct bfd_link_info *info) +{ + flagword flags; + asection *s; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY); + + BFD_ASSERT (!info->shared); + + s = bfd_make_section_with_flags (abfd, ".got.plt", + SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if (s == NULL || !bfd_set_section_alignment (abfd, s, 4)) + return FALSE; + htab->sgotplt = s; + + /* Create the .plt, .rel.plt, .dynbss and .rel.bss sections. */ + if (!_bfd_elf_create_dynamic_sections (abfd, info)) + return FALSE; + + /* Cache the sections created above. */ + htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss"); + htab->srelbss = bfd_get_section_by_name (abfd, ".rel.bss"); + htab->srelplt = bfd_get_section_by_name (abfd, ".rel.plt"); + htab->splt = bfd_get_section_by_name (abfd, ".plt"); + if (!htab->sdynbss + || !htab->srelbss + || !htab->srelplt + || !htab->splt) + abort (); + + /* Align .plt to 32 bytes, so that no PLT entry crosses a + cache line. */ + if (! bfd_set_section_alignment (abfd, htab->splt, 5)) + return FALSE; + + /* Work out the PLT sizes. */ + htab->plt_header_size = 4 * ARRAY_SIZE (mips_non_pic_exec_plt0_entry); + htab->plt_entry_size = 4 * ARRAY_SIZE (mips_non_pic_exec_plt_entry); + htab->large_plt_entry_size = + 4 * ARRAY_SIZE (mips_non_pic_large_exec_plt_entry); + + return TRUE; +} + /* Create dynamic sections when linking against a dynamic object. */ bfd_boolean @@ -6182,6 +6317,18 @@ _bfd_mips_elf_create_dynamic_sections (b if (! mips_elf_create_got_section (abfd, info, FALSE)) return FALSE; + /* VxWorks and non-PIC ABI code also need a .got.plt section. */ + if (htab->is_vxworks) + { + s = bfd_make_section_with_flags (abfd, ".got.plt", + SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS + | SEC_IN_MEMORY | SEC_LINKER_CREATED); + if (s == NULL || !bfd_set_section_alignment (abfd, s, 4)) + return FALSE; + + htab->sgotplt = s; + } + if (! mips_elf_rel_dyn_section (info, TRUE)) return FALSE; @@ -6342,6 +6489,12 @@ _bfd_mips_elf_create_dynamic_sections (b } } + /* If creating a (non-shared) object using the non-PIC ABI, + we also need a PLT etc. */ + if (htab->is_non_pic + && !_bfd_mips_elf_create_nonpic_dynamic_sections (abfd, info)) + return FALSE; + return TRUE; } @@ -6498,6 +6651,24 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s sym_hashes = elf_sym_hashes (abfd); extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; + /* Check if this is the first non-PIC file encountered during an + executable link. We have to check the input file's flags, + since merge_private_data is not called until later. */ + if (!htab->is_non_pic && !info->shared) + { + flagword flags; + + flags = elf_elfheader (abfd)->e_flags; + if ((flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC) + { + htab->is_non_pic = TRUE; + htab->non_pic_bfd = abfd; + if (elf_hash_table (info)->dynamic_sections_created) + if (!_bfd_mips_elf_create_nonpic_dynamic_sections (dynobj, info)) + return FALSE; + } + } + /* Check for the mips16 stub sections. */ name = bfd_get_section_name (abfd, sec); @@ -6823,7 +6994,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s are handled using copy relocs or PLT stubs, so there's no need to add a dynamic relocation here. */ if (dynobj == NULL - && (info->shared || (h != NULL && !htab->is_vxworks)) + && (info->shared + || (h != NULL && !htab->is_vxworks && !htab->is_non_pic)) && (sec->flags & SEC_ALLOC) != 0) elf_hash_table (info)->dynobj = dynobj = abfd; break; @@ -6835,8 +7007,6 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s if (h) { - ((struct mips_elf_link_hash_entry *) h)->is_relocation_target = TRUE; - /* Relocations against the special VxWorks __GOTT_BASE__ and __GOTT_INDEX__ symbols must be left to the loader. Allocate room for them in .rela.dyn. */ @@ -6890,7 +7060,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s case R_MIPS_CALL_LO16: if (h != NULL) { - /* VxWorks call relocations point the function's .got.plt + /* VxWorks call relocations point at the function's .got.plt entry, which will be allocated by adjust_dynamic_symbol. Otherwise, this symbol requires a global GOT entry. */ if ((!htab->is_vxworks || h->forced_local) @@ -6899,7 +7069,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s /* We need a stub, not a plt entry for the undefined function. But we record it as if it needs plt. See - _bfd_elf_adjust_dynamic_symbol. */ + _bfd_elf_adjust_dynamic_symbol. Note that these relocations + are always used for PIC calls, even when using the new + non-PIC ABI. */ h->needs_plt = 1; h->type = STT_FUNC; } @@ -7006,10 +7178,15 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s case R_MIPS_32: case R_MIPS_REL32: case R_MIPS_64: + if (h != NULL) + h->non_got_ref = TRUE; /* In VxWorks executables, references to external symbols are handled using copy relocs or PLT stubs, so there's - no need to add a .rela.dyn entry for this relocation. */ - if ((info->shared || (h != NULL && !htab->is_vxworks)) + no need to add a .rela.dyn entry for this relocation. + Likewise for the non-PIC ABI, if we already know that + we are using it. */ + if ((info->shared + || (h != NULL && !htab->is_vxworks && !htab->is_non_pic)) && (sec->flags & SEC_ALLOC) != 0) { if (sreloc == NULL) @@ -7034,7 +7211,9 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s struct mips_elf_link_hash_entry *hmips; /* We only need to copy this reloc if the symbol is - defined in a dynamic object. */ + defined in a dynamic object. We do not need to + do so at all if we find a non-PIC file later in + the link. */ hmips = (struct mips_elf_link_hash_entry *) h; ++hmips->possibly_dynamic_relocs; if (MIPS_ELF_READONLY_SECTION (sec)) @@ -7048,7 +7227,11 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s table index greater that DT_MIPS_GOTSYM if there are dynamic relocations against it. This does not apply to VxWorks, which does not have the usual coupling - between global GOT entries and .dynsym entries. */ + between global GOT entries and .dynsym entries. + If this link turns out to be a non-PIC one (i.e. we + have only seen PIC files so far, but find a non-PIC + one later), then this will not have been necessary; + but it is harmless in that case. */ if (h != NULL && !htab->is_vxworks) { if (dynobj == NULL) @@ -7079,11 +7262,21 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s case R_MIPS_GPREL16: case R_MIPS_LITERAL: case R_MIPS_GPREL32: + if (h != NULL + && (r_type == R_MIPS_GPREL16 || r_type == R_MIPS_GPREL32)) + h->non_got_ref = TRUE; + if (SGI_COMPAT (abfd)) mips_elf_hash_table (info)->compact_rel_size += sizeof (Elf32_External_crinfo); break; + case R_MIPS_HI16: + case R_MIPS_LO16: + if (h != NULL && strcmp (h->root.root.string, "_gp_disp") != 0) + h->non_got_ref = TRUE; + break; + /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ case R_MIPS_GNU_VTINHERIT: @@ -7106,19 +7299,19 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s /* We must not create a stub for a symbol that has relocations related to taking the function's address. This doesn't apply to - VxWorks, where CALL relocs refer to a .got.plt entry instead of - a normal .got entry. */ + VxWorks or the non-PIC ABI, where CALL relocs refer to a + .got.plt entry instead of a normal .got entry. */ if (!htab->is_vxworks && h != NULL) switch (r_type) { - default: - ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE; - break; case R_MIPS_CALL16: case R_MIPS_CALL_HI16: case R_MIPS_CALL_LO16: case R_MIPS_JALR: break; + default: + ((struct mips_elf_link_hash_entry *) h)->no_fn_stub = TRUE; + break; } /* If this reloc is not a 16 bit call, and it has a global @@ -7133,6 +7326,36 @@ _bfd_mips_elf_check_relocs (bfd *abfd, s mh = (struct mips_elf_link_hash_entry *) h; mh->need_fn_stub = TRUE; } + + /* Refuse invalid relocations when creating a shared library. Do + not refuse R_MIPS_32 / R_MIPS_64; they're not PIC, but we'll set + TEXTREL and the result will be fine. */ + if (info->shared + && (sec->flags & SEC_ALLOC) != 0 + && (sec->flags & SEC_READONLY) != 0) + { + switch (r_type) + { + case R_MIPS_HI16: + /* Don't refuse R_MIPS_HI16 relocation if it's a part of + compound relocation or against _gp_disp. */ + if (NEWABI_P (dynobj) + || (h != NULL + && strcmp (h->root.root.string, "_gp_disp") == 0)) + break; + /* FALLTHROUGH */ + case R_MIPS_26: + howto = MIPS_ELF_RTYPE_TO_HOWTO (abfd, r_type, FALSE); + (*_bfd_error_handler) + (_("%B: relocation %s against `%s' can not be used when making a shared object; recompile with -fPIC"), + abfd, howto->name, + (h) ? h->root.root.string : "a local symbol"); + bfd_set_error (bfd_error_bad_value); + return FALSE; + default: + break; + } + } } return TRUE; @@ -7299,6 +7522,61 @@ _bfd_mips_relax_section (bfd *abfd, asec return FALSE; } +/* Return the size in bytes that the next PLT entry to be added to + htab->splt will require. */ +static bfd_vma +mips_elf_next_plt_entry_size (struct mips_elf_link_hash_table *htab) +{ + /* If we have fewer than MIPS_NONPIC_LARGE_PLT_THRESHOLD entries + currently in the PLT, the next entry to be added will be a normal + "small" PLT entry; otherwise it must be a large PLT entry. */ + if (htab->splt->size - htab->plt_header_size + >= htab->plt_entry_size * MIPS_NONPIC_LARGE_PLT_THRESHOLD) + return htab->large_plt_entry_size; + else + return htab->plt_entry_size; +} + +/* Create an old-style .MIPS.stubs entry for a symbol not defined in a + regular file. The symbol's value is pointed at the .MIPS.stubs entry + to provide a canonical function address. */ + +static bfd_boolean +mips_elf_create_old_style_stub (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + bfd *dynobj = elf_hash_table (info)->dynobj; + struct mips_elf_link_hash_table *htab = mips_elf_hash_table (info); + asection *s; + + BFD_ASSERT (dynobj != NULL); + BFD_ASSERT (htab != NULL); + BFD_ASSERT (elf_hash_table (info) != NULL); + BFD_ASSERT (!((struct mips_elf_link_hash_entry *) h)->no_fn_stub + && h->needs_plt + && !h->def_regular); + + if (!elf_hash_table (info)->dynamic_sections_created) + return TRUE; + + /* Find the .stub section. */ + s = bfd_get_section_by_name (dynobj, + MIPS_ELF_STUB_SECTION_NAME (dynobj)); + BFD_ASSERT (s != NULL); + + h->root.u.def.section = s; + h->root.u.def.value = s->size; + + h->plt.offset = s->size; + + /* Make room for this stub code. */ + s->size += htab->function_stub_size; + + /* The last half word of the stub will be filled with the index + of this symbol in .dynsym section. */ + return TRUE; +} + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -7311,11 +7589,15 @@ _bfd_mips_elf_adjust_dynamic_symbol (str { bfd *dynobj; struct mips_elf_link_hash_entry *hmips; - asection *s; struct mips_elf_link_hash_table *htab; htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; + hmips = (struct mips_elf_link_hash_entry *) h; + + /* VxWorks and the non-PIC ABI are handled elsewhere. */ + if (htab->is_vxworks || htab->is_non_pic) + return _bfd_mips_plt_adjust_dynamic_symbol (info, h); /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL @@ -7328,7 +7610,6 @@ _bfd_mips_elf_adjust_dynamic_symbol (str /* If this symbol is defined in a dynamic object, we need to copy any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output file. */ - hmips = (struct mips_elf_link_hash_entry *) h; if (! info->relocatable && hmips->possibly_dynamic_relocs != 0 && (h->root.type == bfd_link_hash_defweak @@ -7343,39 +7624,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (str } /* For a function, create a stub, if allowed. */ - if (! hmips->no_fn_stub - && h->needs_plt) - { - if (! elf_hash_table (info)->dynamic_sections_created) - return TRUE; - - /* If this symbol is not defined in a regular file, then set - the symbol to the stub location. This is required to make - function pointers compare as equal between the normal - executable and the shared library. */ - if (!h->def_regular) - { - /* We need .stub section. */ - s = bfd_get_section_by_name (dynobj, - MIPS_ELF_STUB_SECTION_NAME (dynobj)); - BFD_ASSERT (s != NULL); - - h->root.u.def.section = s; - h->root.u.def.value = s->size; - - /* XXX Write this stub address somewhere. */ - h->plt.offset = s->size; - - /* Make room for this stub code. */ - s->size += htab->function_stub_size; - - /* The last half word of the stub will be filled with the index - of this symbol in .dynsym section. */ - return TRUE; - } - } - else if ((h->type == STT_FUNC) - && !h->needs_plt) + if (!hmips->no_fn_stub && h->needs_plt && !h->def_regular) + return mips_elf_create_old_style_stub (info, h); + else if (h->type == STT_FUNC && !h->needs_plt) { /* This will set the entry for this symbol in the GOT to 0, and the dynamic linker will take care of this. */ @@ -7401,94 +7652,188 @@ _bfd_mips_elf_adjust_dynamic_symbol (str return TRUE; } -/* Likewise, for VxWorks. */ +/* Likewise, for ABIs requiring procedure linkage tables (the non-PIC + ABI, and that of VxWorks). */ bfd_boolean -_bfd_mips_vxworks_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) +_bfd_mips_plt_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) { + bfd_boolean needs_plt_entry = FALSE; bfd *dynobj; struct mips_elf_link_hash_entry *hmips; struct mips_elf_link_hash_table *htab; + int reloc_size; htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; hmips = (struct mips_elf_link_hash_entry *) h; - /* Make sure we know what is going on here. */ + /* The code below is only for VxWorks or applications using the + non-PIC ABI. */ + BFD_ASSERT (htab->is_vxworks || htab->is_non_pic); BFD_ASSERT (dynobj != NULL && (h->needs_plt - || h->needs_copy || h->u.weakdef != NULL || (h->def_dynamic && h->ref_regular && !h->def_regular))); - /* If the symbol is defined by a dynamic object, we need a PLT stub if + /* Note applicable to the non-PIC ABI only. + On entry to this function, h->needs_plt is set just when there is + a call from PIC code to the symbol under consideration. Unless the + symbol now transpires to be local or have its address taken, this + means that an old-style .MIPS.stubs entry is required. We set + needs_plt_entry during this function if we are using the non-PIC ABI + and discover that the symbol requires a PLT entry. Both of these + flags may be set together. On exit from this function, h->needs_plt + details whether a .MIPS.stubs entry was created. */ + + /* If the symbol is defined by a dynamic object, we need a PLT entry if either (a) we want to branch to the symbol or (b) we're linking an executable that needs a canonical function address. In the latter - case, the canonical address will be the address of the executable's - load stub. */ + case, the canonical address will be that of the PLT entry. */ if ((hmips->is_branch_target || (!info->shared && h->type == STT_FUNC - && hmips->is_relocation_target)) + && h->non_got_ref)) && h->def_dynamic && h->ref_regular && !h->def_regular && !h->forced_local) - h->needs_plt = 1; + { + /* This is the only place where we mark a symbol as requiring a + PLT entry under the non-PIC ABI. */ + if (htab->is_non_pic) + needs_plt_entry = TRUE; - /* Locally-binding symbols do not need a PLT stub; we can refer to - the functions directly. */ + if (htab->is_vxworks) + h->needs_plt = TRUE; + } + /* Locally-binding symbols do not need a PLT or a .MIPS.stubs entry; + we can refer to the functions directly. */ else if (h->needs_plt && (SYMBOL_CALLS_LOCAL (info, h) || (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT && h->root.type == bfd_link_hash_undefweak))) { - h->needs_plt = 0; + h->needs_plt = FALSE; return TRUE; } - if (h->needs_plt) + /* If using the non-PIC ABI, create a .MIPS.stubs entry for this + symbol if required. The symbol must not have had its address + taken; it must have been marked as requiring a stub previously; + and it must not be defined in a regular file. */ + if (htab->is_non_pic && h->needs_plt && !hmips->no_fn_stub) + { + if (!mips_elf_create_old_style_stub (info, h)) + return FALSE; + /* We continue if the stub was created successfully; as above, we + may need a PLT entry too. */ + } + + /* Under the non-PIC ABI, symbols marked as requiring non-PIC to PIC + call stubs (such symbols being defined in PIC code) should by definition + never be undefined in a regular file. It follows that such symbols + should never have PLT entries associated with them, nor copy relocs. */ + BFD_ASSERT (!htab->is_non_pic + || !hmips->has_non_pic_to_pic_stub + || !needs_plt_entry + || !h->non_got_ref); + + /* Calculate the number of bytes required for a relocation + in .rel[a].plt. */ + if (htab->is_vxworks) + reloc_size = sizeof (Elf32_External_Rela); + else + reloc_size = sizeof (Elf32_External_Rel); + + if ((htab->is_vxworks && h->needs_plt) + || (htab->is_non_pic && needs_plt_entry)) { + /* VxWorks can have PLT entries in shared libraries; but this never + happens with the non-PIC ABI. In the non-PIC case, every symbol + being dealt with here should be undefined in a regular file. */ + BFD_ASSERT (htab->is_vxworks || !h->def_regular); + /* If this is the first symbol to need a PLT entry, allocate room - for the header, and for the header's .rela.plt.unloaded entries. */ + for the first PLT (header) entry, and on VxWorks for the header's + .rela.plt.unloaded entries. For the non-PIC ABI, also allocate + room at the start of .got.plt for the PLT resolver and link + map pointers. */ if (htab->splt->size == 0) { - htab->splt->size += htab->plt_header_size; - if (!info->shared) - htab->srelplt2->size += 2 * sizeof (Elf32_External_Rela); + htab->splt->size = htab->plt_header_size; + if (!info->shared && htab->is_vxworks) + { + BFD_ASSERT (htab->srelplt2->size == 0); + htab->srelplt2->size = 2 * reloc_size; + } + if (htab->is_non_pic) + { + BFD_ASSERT (htab->sgotplt->size == 0); + /* Leave space for the PLT resolver and link map pointers. */ + htab->sgotplt->size = 8; + } + BFD_ASSERT (htab->srelplt->size == 0); } /* Assign the next .plt entry to this symbol. */ - h->plt.offset = htab->splt->size; - htab->splt->size += htab->plt_entry_size; + if (htab->is_vxworks) + h->plt.offset = htab->splt->size; + else + hmips->plt_entry_offset = htab->splt->size; + htab->splt->size += mips_elf_next_plt_entry_size (htab); /* If the output file has no definition of the symbol, set the - symbol's value to the address of the stub. Point at the PLT - load stub rather than the lazy resolution stub; this stub - will become the canonical function address. */ + symbol's value to the address of the stub. Note the + assertion above that h->def_regular will always be false + under the non-PIC ABI. */ if (!info->shared && !h->def_regular) { h->root.u.def.section = htab->splt; - h->root.u.def.value = h->plt.offset; - h->root.u.def.value += 8; + h->root.u.def.value = htab->is_vxworks ? + h->plt.offset : hmips->plt_entry_offset; + if (htab->is_non_pic) + { + /* Make sure the dynamic linker knows that the symbol's value + points at a PLT entry and not at a .MIPS.stubs entry. */ + h->other = STO_MIPS_PLT; + } + /* On VxWorks, point at the PLT load stub rather than the + lazy resolution stub; this stub will become the canonical + function address. */ + if (htab->is_vxworks) + h->root.u.def.value += 8; } - /* Make room for the .got.plt entry and the R_JUMP_SLOT relocation. */ + /* Make room for the .got.plt entry, and the R_JUMP_SLOT relocation + in .rel[a].plt. */ htab->sgotplt->size += 4; - htab->srelplt->size += sizeof (Elf32_External_Rela); + htab->srelplt->size += reloc_size; - /* Make room for the .rela.plt.unloaded relocations. */ - if (!info->shared) - htab->srelplt2->size += 3 * sizeof (Elf32_External_Rela); + /* Make room for the .rela.plt.unloaded relocations on VxWorks. */ + if (htab->is_vxworks && !info->shared) + htab->srelplt2->size += 3 * reloc_size; return TRUE; } + /* If we reach this point for non-PIC, then we have created a + .MIPS.stubs stub (unless no_fn_stub) but not a PLT entry since one was + not required. We're done. */ + BFD_ASSERT (!htab->is_non_pic || !needs_plt_entry); + if (htab->is_non_pic && h->needs_plt) + return TRUE; + + /* We should never reach this point on VxWorks or the non-PIC ABI if + we have created a PLT entry or a .MIPS.stubs-style stub + respectively. */ + BFD_ASSERT (!h->needs_plt); + /* If a function symbol is defined by a dynamic object, and we do not - need a PLT stub for it, the symbol's value should be zero. */ + need a PLT entry for it, the symbol's value should be zero. */ if (h->type == STT_FUNC && h->def_dynamic && h->ref_regular @@ -7510,11 +7855,19 @@ _bfd_mips_vxworks_adjust_dynamic_symbol return TRUE; } - /* This is a reference to a symbol defined by a dynamic object which + /* We have a reference to a symbol defined by a dynamic object which is not a function. */ + BFD_ASSERT (h->ref_regular && h->def_dynamic && !h->def_regular); + BFD_ASSERT (h->type != STT_FUNC); + + /* If creating a shared library, we are done. */ if (info->shared) return TRUE; + /* If this symbol does not require a copy reloc, we are done. */ + if (!h->non_got_ref) + return TRUE; + /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be an entry for this symbol in the .dynsym section. The dynamic @@ -7524,10 +7877,14 @@ _bfd_mips_vxworks_adjust_dynamic_symbol determine the address it must put in the global offset table, so both the dynamic object and the regular object will refer to the same memory location for the variable. */ - + BFD_ASSERT (!h->needs_copy); if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { - htab->srelbss->size += sizeof (Elf32_External_Rela); + if (htab->is_non_pic) + mips_elf_allocate_dynamic_relocations (dynobj, info, 1); + else + htab->srelbss->size += sizeof (Elf32_External_Rela); + /* Note that this symbol definitely needs a copy reloc. */ h->needs_copy = 1; } @@ -7560,6 +7917,35 @@ count_section_dynsyms (bfd *output_bfd, return count; } +/* Determine if a symbol requires a non-PIC to PIC call stub to be + created for it. If so, mark it as such and allocate space for the + stub code. */ + +static int +mips_elf_maybe_create_non_pic_to_pic_stub (void *h_ptr, void *htab_ptr) +{ + struct mips_elf_link_hash_entry *h = + (struct mips_elf_link_hash_entry *) h_ptr; + struct mips_elf_link_hash_table *htab = + (struct mips_elf_link_hash_table *) htab_ptr; + + if (h != NULL + && h->root.def_regular + && !h->root.def_dynamic + && !h->has_non_pic_to_pic_stub + && h->is_branch_target + && !NON_PIC_P (h->root.root.u.def.section->owner)) + { + BFD_ASSERT (htab->snonpictopic != NULL); + + h->plt_entry_offset = htab->snonpictopic->size; + htab->snonpictopic->size += 4 * ARRAY_SIZE (mips_non_pic_to_pic_stub); + h->has_non_pic_to_pic_stub = TRUE; + } + + return 1; +} + /* This function is called after all the input files have been read, and the input sections have been assigned to output sections. We check for any mips16 stub sections that we can discard. */ @@ -7702,6 +8088,25 @@ _bfd_mips_elf_always_size_sections (bfd } htab->computed_got_sizes = TRUE; + /* Identify symbols that require non-PIC to PIC call stubs. + Allocate space for any such stubs. */ + if (htab->is_non_pic) + { + BFD_ASSERT (htab->snonpictopic != NULL); + + elf_link_hash_traverse (elf_hash_table (info), + mips_elf_maybe_create_non_pic_to_pic_stub, htab); + if (htab->snonpictopic->size != 0) + { + htab->snonpictopic->contents = bfd_zalloc (output_bfd, + htab->snonpictopic->size); + if (htab->snonpictopic->contents == NULL) + return FALSE; + } + else + htab->snonpictopic->flags |= SEC_EXCLUDE; + } + return TRUE; } @@ -7887,11 +8292,19 @@ _bfd_mips_elf_size_dynamic_sections (bfd else if (SGI_COMPAT (output_bfd) && CONST_STRNEQ (name, ".compact_rel")) s->size += mips_elf_hash_table (info)->compact_rel_size; + else if (s == htab->splt) + { + /* If the last PLT entry has a branch delay slot, allocate + room for an extra nop to fill the delay slot. */ + if (s->size - htab->plt_header_size + <= htab->plt_entry_size * MIPS_NONPIC_LARGE_PLT_THRESHOLD) + s->size += 4; + } else if (! CONST_STRNEQ (name, ".init") - && s != htab->sgotplt - && s != htab->splt) + && s != htab->sgotplt) { - /* It's not one of our sections, so don't allocate space. */ + /* It's not one of our sections, or it's the non-PIC to PIC stubs + section that is allocated elsewhere, so don't allocate space. */ continue; } @@ -8034,6 +8447,24 @@ _bfd_mips_elf_size_dynamic_sections (bfd if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_GOTSYM, 0)) return FALSE; + if (htab->is_non_pic && htab->splt->size > 0) + { + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTREL, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_JMPREL, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTRELSZ, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_PLTGOT, 0)) + return FALSE; + + if (! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_RWPLT, 0)) + return FALSE; + } + if (IRIX_COMPAT (dynobj) == ict_irix5 && ! MIPS_ELF_ADD_DYNAMIC_ENTRY (info, DT_MIPS_HIPAGENO, 0)) return FALSE; @@ -8505,11 +8936,14 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd const char *name; int idx; struct mips_elf_link_hash_table *htab; + struct mips_elf_link_hash_entry *hmips; + + hmips = (struct mips_elf_link_hash_entry *) h; htab = mips_elf_hash_table (info); dynobj = elf_hash_table (info)->dynobj; - if (h->plt.offset != MINUS_ONE) + if (h->plt.offset != MINUS_ONE && h->needs_plt) { asection *s; bfd_byte stub[MIPS_FUNCTION_STUB_BIG_SIZE]; @@ -8556,7 +8990,7 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd bfd_put_32 (output_bfd, STUB_LI16S (output_bfd, h->dynindx), stub + idx); - BFD_ASSERT (h->plt.offset <= s->size); + BFD_ASSERT (h->plt.offset <= s->size - htab->function_stub_size); memcpy (s->contents + h->plt.offset, stub, htab->function_stub_size); /* Mark the symbol as undefined. plt.offset != -1 occurs @@ -8569,6 +9003,107 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset); } + else if (hmips->plt_entry_offset != (bfd_vma) -1 + && !hmips->has_non_pic_to_pic_stub) + { + /* Fill in the PLT, .got.plt and .rel.plt entries for this symbol. */ + + bfd_byte *loc; + bfd_vma plt_address, plt_index, gotplt_address; + Elf_Internal_Rela rel; + static const bfd_vma *plt_entry; + bfd_vma gotplt_address_high, gotplt_address_low; + + BFD_ASSERT (!info->shared); + BFD_ASSERT (h->dynindx != -1); + BFD_ASSERT (htab->splt != NULL); + BFD_ASSERT (hmips->plt_entry_offset < htab->splt->size); + + /* Calculate the address of the .plt entry. */ + plt_address = (htab->splt->output_section->vma + + htab->splt->output_offset + + hmips->plt_entry_offset); + + /* Calculate the (0-based) index, in words, of the .rel.plt entry, + taking into account whether this is a large PLT entry or not. + The index into .got.plt is this index plus two (to skip over + the PLT resolver and link map pointers at the start of the + PLT GOT.) */ + if (hmips->plt_entry_offset + >= htab->plt_header_size + + htab->plt_entry_size * MIPS_NONPIC_LARGE_PLT_THRESHOLD) + /* This entry is a large PLT entry. */ + plt_index = ((hmips->plt_entry_offset - htab->plt_header_size + - htab->plt_entry_size * MIPS_NONPIC_LARGE_PLT_THRESHOLD) + / htab->large_plt_entry_size + + MIPS_NONPIC_LARGE_PLT_THRESHOLD); + else + { + /* This entry is a normal PLT entry. */ + plt_index = ((hmips->plt_entry_offset - htab->plt_header_size) + / htab->plt_entry_size); + BFD_ASSERT (plt_index < MIPS_NONPIC_LARGE_PLT_THRESHOLD); + } + + /* Calculate the address of the .got.plt entry. The addition of 8 + is to allow for the PLT resolver and link map pointers at the + start of .got.plt. */ + gotplt_address = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + + 8 + plt_index * 4); + + /* Split the address of the .got.plt entry into high and low + parts. The 0x8000 bias is to compensate for the fact that the addiu + instruction into which the low part will be written accepts a + _signed_ immediate. */ + gotplt_address_high = ((gotplt_address + 0x8000) >> 16) & 0xffff; + gotplt_address_low = gotplt_address & 0xffff; + + /* Fill in the initial value (the address of the first PLT entry) + of the .got.plt entry. */ + bfd_put_32 (output_bfd, plt_address - hmips->plt_entry_offset, + htab->sgotplt->contents + 8 + plt_index * 4); + + /* Find out where the .plt entry should go. + Note the use of hmips->plt_entry_offset to save distinguishing between + large and small PLT entries. */ + loc = htab->splt->contents + hmips->plt_entry_offset; + + /* Choose the PLT entry template to use and write it, suitably + filled, to the output bfd. */ + if (plt_index >= MIPS_NONPIC_LARGE_PLT_THRESHOLD) + { + /* Large PLT entry. */ + plt_entry = mips_non_pic_large_exec_plt_entry; + bfd_put_32 (output_bfd, plt_entry[0] | gotplt_address_high, loc); + bfd_put_32 (output_bfd, plt_entry[1] | gotplt_address_low, loc + 4); + bfd_put_32 (output_bfd, plt_entry[2] | (plt_index >> 16), loc + 8); + bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + bfd_put_32 (output_bfd, plt_entry[4] | (plt_index & 0xffff), + loc + 16); + bfd_put_32 (output_bfd, plt_entry[5], loc + 20); + bfd_put_32 (output_bfd, plt_entry[6], loc + 24); + bfd_put_32 (output_bfd, plt_entry[7], loc + 28); + } + else + { + /* Normal PLT entry. */ + plt_entry = mips_non_pic_exec_plt_entry; + bfd_put_32 (output_bfd, plt_entry[0] | gotplt_address_high, loc); + bfd_put_32 (output_bfd, plt_entry[1] | gotplt_address_low, loc + 4); + bfd_put_32 (output_bfd, plt_entry[2] | plt_index, loc + 8); + bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + } + + /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */ + loc = htab->srelplt->contents + plt_index * sizeof (Elf32_External_Rel); + rel.r_offset = gotplt_address; + rel.r_info = ELF32_R_INFO (h->dynindx, R_MIPS_JUMP_SLOT); + bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + + /* Mark the symbol as undefined. */ + sym->st_shndx = SHN_UNDEF; + } BFD_ASSERT (h->dynindx != -1 || h->forced_local); @@ -8718,6 +9253,29 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd } } + /* Emit a copy reloc, if needed. */ + if (htab->is_non_pic && h->needs_copy) + { + asection *relsec; + Elf_Internal_Rela rel; + bfd_byte *reloff; /* dyn.rel offset for this copy reloc */ + + relsec = mips_elf_rel_dyn_section (info, FALSE); + BFD_ASSERT (relsec != NULL); + BFD_ASSERT (h->dynindx != -1); + + reloff = relsec->contents + + (relsec->reloc_count * sizeof (Elf32_External_Rel)); + + rel.r_addend = 0; + rel.r_info = ELF_R_INFO (output_bfd, (unsigned long) h->dynindx, R_MIPS_COPY); + rel.r_offset = (h->root.u.def.section->output_section->vma + + h->root.u.def.section->output_offset + + h->root.u.def.value); + bfd_elf32_swap_reloc_out (output_bfd, &rel, reloff); + ++relsec->reloc_count; + } + /* If this is a mips16 symbol, force the value to be even. */ if (sym->st_other == STO_MIPS16) sym->st_value &= ~1; @@ -8897,6 +9455,41 @@ _bfd_mips_vxworks_finish_dynamic_symbol return TRUE; } +/* Install the PLT header for a non-PIC executable. */ + +static void +mips_non_pic_finish_plt (bfd *output_bfd, struct bfd_link_info *info) +{ + bfd_byte *loc; + bfd_vma plt_address; + static const bfd_vma *plt_entry; + struct mips_elf_link_hash_table *htab; + bfd_vma got_plt, got_plt_high, got_plt_low; + + htab = mips_elf_hash_table (info); + plt_entry = mips_non_pic_exec_plt0_entry; + + /* Calculate the address of .got.plt and split it into high and low + parts. The 0x8000 bias is to compensate for the fact that the addiu + instruction into which the low part will be written accepts a + _signed_ immediate. */ + got_plt = htab->sgotplt->output_section->vma + htab->sgotplt->output_offset; + got_plt_high = ((got_plt + 0x8000) >> 16) & 0xffff; + got_plt_low = got_plt & 0xffff; + + /* Calculate the address of the PLT header. */ + plt_address = htab->splt->output_section->vma + htab->splt->output_offset; + + /* Install the PLT header. */ + loc = htab->splt->contents; + bfd_put_32 (output_bfd, plt_entry[0] | got_plt_high, loc); + bfd_put_32 (output_bfd, plt_entry[1] | got_plt_low, loc + 4); + bfd_put_32 (output_bfd, plt_entry[2], loc + 8); + bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + bfd_put_32 (output_bfd, plt_entry[4], loc + 16); + bfd_put_32 (output_bfd, plt_entry[5], loc + 20); +} + /* Install the PLT header for a VxWorks executable and finalize the contents of .rela.plt.unloaded. */ @@ -9059,20 +9652,21 @@ _bfd_mips_elf_finish_dynamic_sections (b case DT_PLTGOT: name = ".got"; - if (htab->is_vxworks) - { - /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning - of the ".got" section in DYNOBJ. */ - s = bfd_get_section_by_name (dynobj, name); - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; - } - else - { - s = bfd_get_section_by_name (output_bfd, name); - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->vma; - } + /* _GLOBAL_OFFSET_TABLE_ is defined to be the beginning + of the ".got" section in DYNOBJ. */ + s = bfd_get_section_by_name (dynobj, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->output_section->vma + s->output_offset; + break; + + case DT_MIPS_PLTGOT: + BFD_ASSERT (htab->is_non_pic); + dyn.d_un.d_val = (htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset); + break; + + case DT_MIPS_RWPLT: + BFD_ASSERT (htab->is_non_pic); break; case DT_MIPS_RLD_VERSION: @@ -9159,17 +9753,17 @@ _bfd_mips_elf_finish_dynamic_sections (b break; case DT_PLTREL: - BFD_ASSERT (htab->is_vxworks); - dyn.d_un.d_val = DT_RELA; + BFD_ASSERT (htab->is_vxworks || htab->is_non_pic); + dyn.d_un.d_val = htab->is_vxworks ? DT_RELA : DT_REL; break; case DT_PLTRELSZ: - BFD_ASSERT (htab->is_vxworks); + BFD_ASSERT (htab->is_vxworks || htab->is_non_pic); dyn.d_un.d_val = htab->srelplt->size; break; case DT_JMPREL: - BFD_ASSERT (htab->is_vxworks); + BFD_ASSERT (htab->is_vxworks || htab->is_non_pic); dyn.d_un.d_val = (htab->srelplt->output_section->vma + htab->srelplt->output_offset); break; @@ -9407,6 +10001,10 @@ _bfd_mips_elf_finish_dynamic_sections (b else mips_vxworks_finish_exec_plt (output_bfd, info); } + + if (htab->is_non_pic && htab->splt && htab->splt->size > 0) + mips_non_pic_finish_plt (output_bfd, info); + return TRUE; } @@ -9994,6 +10592,9 @@ _bfd_mips_elf_copy_indirect_symbol (stru dirmips->readonly_reloc = TRUE; if (indmips->no_fn_stub) dirmips->no_fn_stub = TRUE; + if (indmips->has_non_pic_to_pic_stub) + dirmips->has_non_pic_to_pic_stub = TRUE; + dirmips->is_branch_target |= indmips->is_branch_target; if (dirmips->tls_type == 0) dirmips->tls_type = indmips->tls_type; @@ -10540,6 +11141,7 @@ _bfd_mips_elf_link_hash_table_create (bf ret->mips16_stubs_seen = FALSE; ret->computed_got_sizes = FALSE; ret->is_vxworks = FALSE; + ret->is_non_pic = FALSE; ret->small_data_overflow_reported = FALSE; ret->srelbss = NULL; ret->sdynbss = NULL; @@ -10547,6 +11149,7 @@ _bfd_mips_elf_link_hash_table_create (bf ret->srelplt2 = NULL; ret->sgotplt = NULL; ret->splt = NULL; + ret->snonpictopic = NULL; ret->plt_header_size = 0; ret->plt_entry_size = 0; ret->function_stub_size = 0; @@ -10571,6 +11174,7 @@ _bfd_mips_vxworks_link_hash_table_create } return ret; } + /* We need to use a special link routine to handle the .reginfo and the .mdebug sections. We need to merge all instances of these @@ -11558,12 +12162,6 @@ _bfd_mips_elf_merge_private_bfd_data (bf new_flags &= ~EF_MIPS_UCODE; old_flags &= ~EF_MIPS_UCODE; - /* Don't care about the PIC flags from dynamic objects; they are - PIC by design. */ - if ((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0 - && (ibfd->flags & DYNAMIC) != 0) - new_flags &= ~ (EF_MIPS_PIC | EF_MIPS_CPIC); - if (new_flags == old_flags) return TRUE; @@ -11585,19 +12183,18 @@ _bfd_mips_elf_merge_private_bfd_data (bf break; } } - if (null_input_bfd) + /* Dynamic objects normally have no sections, and do not reach + here - but they might if used as DYNOBJ. */ + if (null_input_bfd || (ibfd->flags & DYNAMIC) != 0) return TRUE; ok = TRUE; if (((new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0) != ((old_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) != 0)) - { - (*_bfd_error_handler) - (_("%B: warning: linking PIC files with non-PIC files"), - ibfd); - ok = TRUE; - } + (*_bfd_error_handler) + (_("%B: warning: linking PIC files with non-PIC files"), + ibfd); if (new_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) elf_elfheader (obfd)->e_flags |= EF_MIPS_CPIC; @@ -11805,6 +12402,10 @@ _bfd_mips_elf_get_target_dtag (bfd_vma d return "DT_MIPS_GP_VALUE"; case DT_MIPS_AUX_DYNAMIC: return "DT_MIPS_AUX_DYNAMIC"; + case DT_MIPS_PLTGOT: + return "DT_MIPS_PLTGOT"; + case DT_MIPS_RWPLT: + return "DT_MIPS_RWPLT"; } } @@ -11939,3 +12540,133 @@ _bfd_mips_elf_common_definition (Elf_Int || sym->st_shndx == SHN_MIPS_ACOMMON || sym->st_shndx == SHN_MIPS_SCOMMON); } + +/* Return address for Ith PLT stub in section PLT, for relocation REL + or (bfd_vma) -1 if it should not be included. */ + +bfd_vma +_bfd_mips_elf_plt_sym_val (bfd_vma i, const asection *plt, + const arelent *rel ATTRIBUTE_UNUSED) +{ + if (i > MIPS_NONPIC_LARGE_PLT_THRESHOLD) + return (plt->vma + 4 * ARRAY_SIZE (mips_non_pic_exec_plt0_entry) + + (MIPS_NONPIC_LARGE_PLT_THRESHOLD + * 4 * ARRAY_SIZE (mips_non_pic_exec_plt_entry)) + + ((i - MIPS_NONPIC_LARGE_PLT_THRESHOLD) + * 4 * ARRAY_SIZE (mips_non_pic_large_exec_plt_entry))); + else + return (plt->vma + 4 * ARRAY_SIZE (mips_non_pic_exec_plt0_entry) + + i * 4 * ARRAY_SIZE (mips_non_pic_exec_plt_entry)); +} + +/* Generate non-PIC to PIC call stubs for all symbols which need them. */ + +static bfd_boolean +mips_elf_nonpic_stub (struct elf_link_hash_entry *h, void *info) +{ + struct bfd_link_info *link_info = info; + struct mips_elf_link_hash_table *htab = mips_elf_hash_table (link_info); + struct bfd *abfd = htab->non_pic_bfd; + struct mips_elf_link_hash_entry *hmips; + bfd_vma target_address, target_high, target_low; + bfd_byte *loc; + asection *sec; + + hmips = (struct mips_elf_link_hash_entry *) h; + if (!hmips->has_non_pic_to_pic_stub) + return TRUE; + + BFD_ASSERT (!link_info->shared); + BFD_ASSERT (h->def_regular); + BFD_ASSERT (!h->def_dynamic); + BFD_ASSERT (htab->snonpictopic != NULL); + BFD_ASSERT (htab->snonpictopic->contents != NULL); + BFD_ASSERT (htab->snonpictopic->output_section != NULL); + BFD_ASSERT (hmips->plt_entry_offset < htab->snonpictopic->size); + + sec = h->root.u.def.section; + + /* Determine the address (to which the stub will branch) of the + symbol, split into two halves as required by the stub + instructions. */ + if (sec->output_section) + target_address = h->root.u.def.value + + sec->output_section->vma + + sec->output_offset; + else + target_address = h->root.u.def.value; + + target_high = ((target_address + 0x8000) >> 16) & 0xffff; + target_low = target_address & 0xffff; + + /* Fill the stub with instructions. */ + loc = htab->snonpictopic->contents + hmips->plt_entry_offset; + bfd_put_32 (abfd, mips_non_pic_to_pic_stub[0] | target_high, loc); + bfd_put_32 (abfd, mips_non_pic_to_pic_stub[1] | target_low, + loc + 4); + bfd_put_32 (abfd, mips_non_pic_to_pic_stub[2], loc + 8); + bfd_put_32 (abfd, mips_non_pic_to_pic_stub[3], loc + 12); + + return TRUE; +} + +void +_bfd_mips_elf_begin_write_processing (bfd *abfd ATTRIBUTE_UNUSED, + struct bfd_link_info *link_info) +{ + struct mips_elf_link_hash_table *htab; + + if (!link_info) + return; + + htab = mips_elf_hash_table (link_info); + if (htab->snonpictopic == NULL || !htab->is_non_pic) + return; + + elf_link_hash_traverse (&htab->root, mips_elf_nonpic_stub, link_info); +} + +/* If performing a non-PIC link, create the section to be used for + non-PIC to PIC call stubs. */ + +bfd_boolean +bfd_mips_elf_maybe_create_non_pic_to_pic_stubs_section + (struct bfd_link_info *info) +{ + struct mips_elf_link_hash_table *htab = mips_elf_hash_table (info); + bfd *abfd = htab->non_pic_bfd; + flagword flags; + + if (info->relocatable) + return TRUE; + if (!htab->is_non_pic) + return TRUE; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_READONLY | SEC_LINKER_CREATED); + htab->snonpictopic = + bfd_make_section_with_flags (abfd, + NON_PIC_TO_PIC_STUB_SECTION_NAME, + flags | SEC_CODE); + if (htab->snonpictopic == NULL + || ! bfd_set_section_alignment (abfd, htab->snonpictopic, + MIPS_ELF_LOG_FILE_ALIGN (abfd))) + return FALSE; + + return TRUE; +} + +void +_bfd_mips_post_process_headers (bfd *abfd, struct bfd_link_info *link_info) +{ + struct mips_elf_link_hash_table *htab; + Elf_Internal_Ehdr *i_ehdrp; + + i_ehdrp = elf_elfheader (abfd); + if (link_info) + { + htab = mips_elf_hash_table (link_info); + if (htab->is_non_pic) + i_ehdrp->e_ident[EI_ABIVERSION] = 1; + } +} Index: bfd/elfxx-mips.h =================================================================== RCS file: /cvs/src/src/bfd/elfxx-mips.h,v retrieving revision 1.38 diff -u -p -r1.38 elfxx-mips.h --- bfd/elfxx-mips.h 27 Feb 2008 17:06:06 -0000 1.38 +++ bfd/elfxx-mips.h 1 Jul 2008 16:08:50 -0000 @@ -50,7 +50,7 @@ extern bfd_boolean _bfd_mips_elf_check_r (bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *); extern bfd_boolean _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); -extern bfd_boolean _bfd_mips_vxworks_adjust_dynamic_symbol +extern bfd_boolean _bfd_mips_plt_adjust_dynamic_symbol (struct bfd_link_info *, struct elf_link_hash_entry *); extern bfd_boolean _bfd_mips_elf_always_size_sections (bfd *, struct bfd_link_info *); @@ -65,6 +65,9 @@ extern bfd_boolean _bfd_mips_elf_finish_ extern bfd_boolean _bfd_mips_vxworks_finish_dynamic_symbol (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, Elf_Internal_Sym *); +extern bfd_boolean _bfd_mips_nonpic_finish_dynamic_symbol + (bfd *, struct bfd_link_info *, struct elf_link_hash_entry *, + Elf_Internal_Sym *); extern bfd_boolean _bfd_mips_elf_finish_dynamic_sections (bfd *, struct bfd_link_info *); extern void _bfd_mips_elf_final_write_processing @@ -146,6 +149,15 @@ extern const struct bfd_elf_special_sect extern bfd_boolean _bfd_mips_elf_common_definition (Elf_Internal_Sym *); +extern bfd_vma _bfd_mips_elf_plt_sym_val + (bfd_vma, const asection *, const arelent *); +extern void _bfd_mips_elf_begin_write_processing + (bfd *abfd, struct bfd_link_info *link_info); +extern bfd_boolean bfd_mips_elf_maybe_create_non_pic_to_pic_stubs_section + (struct bfd_link_info *); +extern void _bfd_mips_post_process_headers + (bfd *abfd, struct bfd_link_info *link_info); + #define elf_backend_common_definition _bfd_mips_elf_common_definition #define elf_backend_name_local_section_symbols \ _bfd_mips_elf_name_local_section_symbols @@ -153,3 +165,5 @@ extern bfd_boolean _bfd_mips_elf_common_ #define elf_backend_eh_frame_address_size _bfd_mips_elf_eh_frame_address_size #define elf_backend_merge_symbol_attribute _bfd_mips_elf_merge_symbol_attribute #define elf_backend_ignore_undef_symbol _bfd_mips_elf_ignore_undef_symbol +#define elf_backend_post_process_headers _bfd_mips_post_process_headers +#define elf_backend_begin_write_processing _bfd_mips_elf_begin_write_processing Index: bfd/reloc.c =================================================================== RCS file: /cvs/src/src/bfd/reloc.c,v retrieving revision 1.174 diff -u -p -r1.174 reloc.c --- bfd/reloc.c 16 Apr 2008 08:51:18 -0000 1.174 +++ bfd/reloc.c 1 Jul 2008 16:08:50 -0000 @@ -2251,7 +2251,7 @@ ENUM ENUMX BFD_RELOC_MIPS_JUMP_SLOT ENUMDOC - MIPS ELF relocations (VxWorks extensions). + MIPS ELF relocations (VxWorks and non-PIC extensions). COMMENT ENUM Index: binutils/readelf.c =================================================================== RCS file: /cvs/src/src/binutils/readelf.c,v retrieving revision 1.411 diff -u -p -r1.411 readelf.c --- binutils/readelf.c 18 Jun 2008 10:49:50 -0000 1.411 +++ binutils/readelf.c 1 Jul 2008 16:08:50 -0000 @@ -1495,6 +1495,9 @@ get_mips_dynamic_type (unsigned long typ case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; + case DT_MIPS_PLTGOT: return "MIPS_PLTGOT"; + case DT_MIPS_RWPLT: return "MIPS_RWPLT"; + default: return NULL; } @@ -7145,6 +7148,7 @@ get_mips_symbol_other (unsigned int othe { case STO_OPTIONAL: return "OPTIONAL"; case STO_MIPS16: return "MIPS16"; + case STO_MIPS_PLT: return "MIPS_PLT"; default: return NULL; } } Index: gas/config/tc-mips.c =================================================================== RCS file: /cvs/src/src/gas/config/tc-mips.c,v retrieving revision 1.388 diff -u -p -r1.388 tc-mips.c --- gas/config/tc-mips.c 12 Jun 2008 21:44:53 -0000 1.388 +++ gas/config/tc-mips.c 1 Jul 2008 16:08:51 -0000 @@ -1854,6 +1854,12 @@ md_begin (void) as_bad (_("-G may not be used in position-independent code")); g_switch_value = 0; } + else if (mips_abicalls) + { + if (g_switch_seen && g_switch_value != 0) + as_bad (_("-G may not be used with abicalls")); + g_switch_value = 0; + } if (! bfd_set_arch_mach (stdoutput, bfd_arch_mips, file_mips_arch)) as_warn (_("Could not set architecture and machine")); @@ -11166,6 +11172,8 @@ struct option md_longopts[] = {"mno-pdr", no_argument, NULL, OPTION_NO_PDR}, #define OPTION_MVXWORKS_PIC (OPTION_ELF_BASE + 11) {"mvxworks-pic", no_argument, NULL, OPTION_MVXWORKS_PIC}, +#define OPTION_NON_PIC_ABICALLS (OPTION_ELF_BASE + 12) + {"mnon-pic-abicalls", no_argument, NULL, OPTION_NON_PIC_ABICALLS}, #endif /* OBJ_ELF */ {NULL, no_argument, NULL, 0} @@ -11574,6 +11582,11 @@ md_parse_option (int c, char *arg) case OPTION_MVXWORKS_PIC: mips_pic = VXWORKS_PIC; break; + + case OPTION_NON_PIC_ABICALLS: + mips_pic = NO_PIC; + mips_abicalls = TRUE; + break; #endif /* OBJ_ELF */ default: Index: include/elf/mips.h =================================================================== RCS file: /cvs/src/src/include/elf/mips.h,v retrieving revision 1.37 diff -u -p -r1.37 mips.h --- include/elf/mips.h 11 Mar 2008 23:21:08 -0000 1.37 +++ include/elf/mips.h 1 Jul 2008 16:08:54 -0000 @@ -662,6 +662,13 @@ extern void bfd_mips_elf32_swap_reginfo_ /* Address of auxiliary .dynamic. */ #define DT_MIPS_AUX_DYNAMIC 0x70000031 + +/* Address of the base of the PLTGOT. */ +#define DT_MIPS_PLTGOT 0x70000032 + +/* Points to the base of a writable PLT. */ +#define DT_MIPS_RWPLT 0x70000034 + /* Flags which may appear in a DT_MIPS_FLAGS entry. */ @@ -723,6 +730,9 @@ extern void bfd_mips_elf32_swap_reginfo_ #define STO_HIDDEN STV_HIDDEN #define STO_PROTECTED STV_PROTECTED +/* Symbol value is the address of a PLT entry. */ +#define STO_MIPS_PLT 0x8 + /* This value is used for a mips16 .text symbol. */ #define STO_MIPS16 0xf0 Index: ld/emulparams/elf32bmip.sh =================================================================== RCS file: /cvs/src/src/ld/emulparams/elf32bmip.sh,v retrieving revision 1.16 diff -u -p -r1.16 elf32bmip.sh --- ld/emulparams/elf32bmip.sh 9 Aug 2007 11:02:24 -0000 1.16 +++ ld/emulparams/elf32bmip.sh 1 Jul 2008 16:08:54 -0000 @@ -35,6 +35,16 @@ OTHER_GOT_SYMBOLS=' . = .; _gp = ALIGN(16) + 0x7ff0; ' +# Only non-PIC abicalls binaries (and VxWorks, which overrides these) +# have .got.plt. It should not go between the definition of _gp and +# the start of .got. It can go in the relro area, because it does not +# need to be anywhere near _gp or small data. Do not set SEPARATE_GOTPLT +# because we might not have a .plt; don't make eight bytes of .data +# relro. +GOT=".got ${RELOCATING-0} : { *(.got) }" +GOTPLT=".got.plt ${RELOCATING-0} : { *(.got.plt) }" +DATA_GOTPLT= + OTHER_SDATA_SECTIONS=" .lit8 ${RELOCATING-0} : { *(.lit8) } .lit4 ${RELOCATING-0} : { *(.lit4) } Index: ld/emulparams/elf32ebmipvxworks.sh =================================================================== RCS file: /cvs/src/src/ld/emulparams/elf32ebmipvxworks.sh,v retrieving revision 1.2 diff -u -p -r1.2 elf32ebmipvxworks.sh --- ld/emulparams/elf32ebmipvxworks.sh 18 May 2007 09:18:18 -0000 1.2 +++ ld/emulparams/elf32ebmipvxworks.sh 1 Jul 2008 16:08:54 -0000 @@ -13,6 +13,9 @@ OTHER_READWRITE_SECTIONS=" .rdata ${RELOCATING-0} : ONLY_IF_RW { *(.rdata) } " unset OTHER_GOT_SYMBOLS +unset GOT +unset GOTPLT +unset DATA_GOTPLT SHLIB_TEXT_START_ADDR=0 unset TEXT_DYNAMIC unset DATA_ADDR Index: ld/emulparams/elf32elmipvxworks.sh =================================================================== RCS file: /cvs/src/src/ld/emulparams/elf32elmipvxworks.sh,v retrieving revision 1.1 diff -u -p -r1.1 elf32elmipvxworks.sh --- ld/emulparams/elf32elmipvxworks.sh 22 Mar 2006 09:28:13 -0000 1.1 +++ ld/emulparams/elf32elmipvxworks.sh 1 Jul 2008 16:08:54 -0000 @@ -4,6 +4,9 @@ OUTPUT_FORMAT="elf32-littlemips-vxworks" BIG_OUTPUT_FORMAT="elf32-bigmips-vxworks" LITTLE_OUTPUT_FORMAT="elf32-littlemips-vxworks" unset OTHER_GOT_SYMBOLS +unset GOT +unset GOTPLT +unset DATA_GOTPLT SHLIB_TEXT_START_ADDR=0 unset TEXT_DYNAMIC unset DATA_ADDR Index: ld/emultempl/mipself.em =================================================================== RCS file: /cvs/src/src/ld/emultempl/mipself.em,v retrieving revision 1.9 diff -u -p -r1.9 mipself.em --- ld/emultempl/mipself.em 19 Jul 2007 19:56:10 -0000 1.9 +++ ld/emultempl/mipself.em 1 Jul 2008 16:08:54 -0000 @@ -19,6 +19,9 @@ # MA 02110-1301, USA. fragment <