From 6d30f5b2dcf2d644300d8ab5ada56cfa22f97bf2 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 17 Jul 2009 09:46:00 +0000 Subject: * elfxx-mips.c (LOAD_INTERLOCKS_P): New define. (_bfd_mips_elf_size_dynamic_sections): For CPUs without load interlocking, the last PLT entry needs a nop in the branch delay slot. (_bfd_mips_elf_finish_dynamic_symbol): For CPUs with load itnerlocking, output the last two PLT entries in reverse order. * ld-mips-elf/pic-and-nonpic-3b.dd, ld-mips-elf/pic-and-nonpic-5b.dd, ld-mips-elf/pic-and-nonpic-6-o32.dd: Updated to use new PLT entries. --- bfd/elfxx-mips.c | 49 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 12 deletions(-) (limited to 'bfd/elfxx-mips.c') diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 034c82a..814ba90 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -662,6 +662,12 @@ static struct mips_got_info *mips_elf_got_for_ibfd /* This will be used when we sort the dynamic relocation records. */ static bfd *reldyn_sorting_bfd; +/* True if ABFD is for CPUs with load interlocking that include + non-MIPS1 CPUs and R3900. */ +#define LOAD_INTERLOCKS_P(abfd) \ + ( ((elf_elfheader (abfd)->e_flags & EF_MIPS_ARCH) != E_MIPS_ARCH_1) \ + || ((elf_elfheader (abfd)->e_flags & EF_MIPS_MACH) == E_MIPS_MACH_3900)) + /* True if ABFD is a PIC object. */ #define PIC_OBJECT_P(abfd) \ ((elf_elfheader (abfd)->e_flags & EF_MIPS_PIC) != 0) @@ -878,7 +884,8 @@ static bfd *reldyn_sorting_bfd; #define CALL_FP_STUB_P(name) CONST_STRNEQ (name, CALL_FP_STUB) /* The format of the first PLT entry in an O32 executable. */ -static const bfd_vma mips_o32_exec_plt0_entry[] = { +static const bfd_vma mips_o32_exec_plt0_entry[] = +{ 0x3c1c0000, /* lui $28, %hi(&GOTPLT[0]) */ 0x8f990000, /* lw $25, %lo(&GOTPLT[0])($28) */ 0x279c0000, /* addiu $28, $28, %lo(&GOTPLT[0]) */ @@ -891,7 +898,8 @@ static const bfd_vma mips_o32_exec_plt0_entry[] = { /* The format of the first PLT entry in an N32 executable. Different because gp ($28) is not available; we use t2 ($14) instead. */ -static const bfd_vma mips_n32_exec_plt0_entry[] = { +static const bfd_vma mips_n32_exec_plt0_entry[] = +{ 0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */ 0x8dd90000, /* lw $25, %lo(&GOTPLT[0])($14) */ 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ @@ -904,7 +912,8 @@ static const bfd_vma mips_n32_exec_plt0_entry[] = { /* The format of the first PLT entry in an N64 executable. Different from N32 because of the increased size of GOT entries. */ -static const bfd_vma mips_n64_exec_plt0_entry[] = { +static const bfd_vma mips_n64_exec_plt0_entry[] = +{ 0x3c0e0000, /* lui $14, %hi(&GOTPLT[0]) */ 0xddd90000, /* ld $25, %lo(&GOTPLT[0])($14) */ 0x25ce0000, /* addiu $14, $14, %lo(&GOTPLT[0]) */ @@ -916,7 +925,8 @@ static const bfd_vma mips_n64_exec_plt0_entry[] = { }; /* The format of subsequent PLT entries. */ -static const bfd_vma mips_exec_plt_entry[] = { +static const bfd_vma mips_exec_plt_entry[] = +{ 0x3c0f0000, /* lui $15, %hi(.got.plt entry) */ 0x01f90000, /* l[wd] $25, %lo(.got.plt entry)($15) */ 0x25f80000, /* addiu $24, $15, %lo(.got.plt entry) */ @@ -924,7 +934,8 @@ static const bfd_vma mips_exec_plt_entry[] = { }; /* The format of the first PLT entry in a VxWorks executable. */ -static const bfd_vma mips_vxworks_exec_plt0_entry[] = { +static const bfd_vma mips_vxworks_exec_plt0_entry[] = +{ 0x3c190000, /* lui t9, %hi(_GLOBAL_OFFSET_TABLE_) */ 0x27390000, /* addiu t9, t9, %lo(_GLOBAL_OFFSET_TABLE_) */ 0x8f390008, /* lw t9, 8(t9) */ @@ -934,7 +945,8 @@ static const bfd_vma mips_vxworks_exec_plt0_entry[] = { }; /* The format of subsequent PLT entries. */ -static const bfd_vma mips_vxworks_exec_plt_entry[] = { +static const bfd_vma mips_vxworks_exec_plt_entry[] = +{ 0x10000000, /* b .PLT_resolver */ 0x24180000, /* li t8, */ 0x3c190000, /* lui t9, %hi(<.got.plt slot>) */ @@ -946,7 +958,8 @@ static const bfd_vma mips_vxworks_exec_plt_entry[] = { }; /* The format of the first PLT entry in a VxWorks shared object. */ -static const bfd_vma mips_vxworks_shared_plt0_entry[] = { +static const bfd_vma mips_vxworks_shared_plt0_entry[] = +{ 0x8f990008, /* lw t9, 8(gp) */ 0x00000000, /* nop */ 0x03200008, /* jr t9 */ @@ -956,7 +969,8 @@ static const bfd_vma mips_vxworks_shared_plt0_entry[] = { }; /* The format of subsequent PLT entries. */ -static const bfd_vma mips_vxworks_shared_plt_entry[] = { +static const bfd_vma mips_vxworks_shared_plt_entry[] = +{ 0x10000000, /* b .PLT_resolver */ 0x24180000 /* li t8, */ }; @@ -8631,8 +8645,10 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, 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 (!htab->is_vxworks && s->size > 0) + room for an extra nop to fill the delay slot. This is + for CPUs without load interlocking. */ + if (! LOAD_INTERLOCKS_P (output_bfd) + && ! htab->is_vxworks && s->size > 0) s->size += 4; } else if (! CONST_STRNEQ (name, ".init") @@ -9355,8 +9371,17 @@ _bfd_mips_elf_finish_dynamic_symbol (bfd *output_bfd, plt_entry = mips_exec_plt_entry; bfd_put_32 (output_bfd, plt_entry[0] | got_address_high, loc); bfd_put_32 (output_bfd, plt_entry[1] | got_address_low | load, loc + 4); - bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8); - bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + + if (! LOAD_INTERLOCKS_P (output_bfd)) + { + bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 8); + bfd_put_32 (output_bfd, plt_entry[3], loc + 12); + } + else + { + bfd_put_32 (output_bfd, plt_entry[3], loc + 8); + bfd_put_32 (output_bfd, plt_entry[2] | got_address_low, loc + 12); + } /* Emit an R_MIPS_JUMP_SLOT relocation against the .got.plt entry. */ mips_elf_output_dynamic_relocation (output_bfd, htab->srelplt, -- cgit v1.1