[PATCH 1/2] MIPS: Compressed PLT/stubs support

Maciej W. Rozycki macro@codesourcery.com
Sat Jun 8 00:22:00 GMT 2013


On Sat, 9 Mar 2013, Richard Sandiford wrote:

> > Index: binutils-fsf-trunk-quilt/bfd/elfxx-mips.c
> > ===================================================================
> > --- binutils-fsf-trunk-quilt.orig/bfd/elfxx-mips.c	2013-03-08 11:09:04.000000000 +0000
> > +++ binutils-fsf-trunk-quilt/bfd/elfxx-mips.c	2013-03-09 02:43:31.765430204 +0000
> > @@ -319,6 +319,32 @@ struct mips_elf_hash_sort_data
> >    long max_non_got_dynindx;
> >  };
> >  
> > +/* We make up to two PLT entries if needed, one for standard MIPS code
> > +   and one for compressed code, either of MIPS16 or microMIPS one.  We
> > +   keep the record of a stub if one is used instead separately, for
> > +   easier processing.  */
> 
> s/either of MIPS16 or microMIPS one/either a MIPS16 or microMIPS one/.
> Suggest "We keep a separate record of traditional lazy-binding stubs,
> for easier processing."

 Done.  I wasn't sure if that would sound better as "either MIPS16 or 
microMIPS one," -- referring to "code" (uncountable) rather than "a PLT 
entry" -- but eventually I decided it sounded better with the article. ;)

> > @@ -5124,13 +5232,55 @@ mips_elf_calculate_relocation (bfd *abfd
> >  		|| h->root.root.type == bfd_link_hash_defweak)
> >  	       && h->root.root.u.def.section)
> >  	{
> > -	  sec = h->root.root.u.def.section;
> > -	  if (sec->output_section)
> > -	    symbol = (h->root.root.u.def.value
> > -		      + sec->output_section->vma
> > -		      + sec->output_offset);
> > +	  if (h->use_plt_entry)
> > +	    {
> > +	      bfd_boolean micromips_p = MICROMIPS_P (abfd);
> > +	      bfd_vma plt_offset;
> > +	      bfd_vma isa_bit;
> > +	      bfd_vma val;
> > +
> > +	      BFD_ASSERT (h->root.plt.plist != NULL);
> > +	      BFD_ASSERT (h->root.plt.plist->mips_offset != MINUS_ONE
> > +			  || h->root.plt.plist->comp_offset != MINUS_ONE);
> > +
> > +	      plt_offset = htab->plt_header_size;
> > +	      if (h->root.plt.plist->comp_offset == MINUS_ONE
> > +		  || (h->root.plt.plist->mips_offset != MINUS_ONE
> > +		      && r_type != R_MIPS16_26 && r_type != R_MICROMIPS_26_S1))
> > +		{
> > +		  isa_bit = 0;
> > +		  target_is_16_bit_code_p = FALSE;
> > +		  target_is_micromips_code_p = FALSE;
> > +		  plt_offset += h->root.plt.plist->mips_offset;
> > +		}
> > +	      else
> > +		{
> > +		  isa_bit = 1;
> > +		  target_is_16_bit_code_p = !micromips_p;
> > +		  target_is_micromips_code_p = micromips_p;
> > +		  plt_offset += (htab->plt_mips_offset
> > +				 + h->root.plt.plist->comp_offset);
> > +		}
> > +	      BFD_ASSERT (plt_offset <= htab->splt->size);
> > +
> > +	      sec = htab->splt;
> > +	      val = plt_offset + isa_bit;
> > +	      /* For VxWorks, point at the PLT load stub rather than the
> > +	         lazy resolution stub.  */
> > +	      if (htab->is_vxworks)
> > +		val += 8;
> > +	      symbol = sec->output_section->vma + sec->output_offset + val;
> > +	    }
> >  	  else
> > -	    symbol = h->root.root.u.def.value;
> > +	    {
> > +	      sec = h->root.root.u.def.section;
> > +	      if (sec->output_section)
> > +		symbol = (h->root.root.u.def.value
> > +			  + sec->output_section->vma
> > +			  + sec->output_offset);
> > +	      else
> > +		symbol = h->root.root.u.def.value;
> > +	    }
> >  	}
> >        else if (h->root.root.type == bfd_link_hash_undefweak)
> >  	/* We allow relocations against undefined weak symbols, giving
> > @@ -5177,12 +5327,6 @@ mips_elf_calculate_relocation (bfd *abfd
> >  	{
> >  	  return bfd_reloc_notsupported;
> >  	}
> > -
> > -      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
> > -      /* If the output section is the PLT section,
> > -         then the target is not microMIPS.  */
> > -      target_is_micromips_code_p = (htab->splt != sec
> > -				    && ELF_ST_IS_MICROMIPS (h->root.other));
> >      }
> >  
> >    /* If this is a reference to a 16-bit function with a stub, we need
> 
> The block of code that you're changing here is simply calculating the
> symbol value.  Now that size_dynamic_sections has set that up for us,
> these two hunks should be dropped, and the test for whether to use a
> compressed PLT entry instead of the symbol value should be made
> afterwards, as it is for things like hard-float and LA25 stubs.

 D'oh, it must have escaped me as the obvious consequence of the 
introduction of mips_elf_set_plt_sym_value.  I haven't merely reverted the 
latter hunk though -- given that we're going to handle the PLT explicitly 
later on now, we want to preset target_is_micromips_code_p according to 
the symbol table here, just as we already do for target_is_16_bit_code_p.

> Maybe something like:
> 
>   /* If compressed PLT entries are available, make sure that we use them
>      for MIPS16 and microMIPS calls.  */
>   else if ((r_type == R_MIPS16_26 || r_type == R_MICROMIPS_26_S1)
> 	   && h != NULL
> 	   && h->use_plt
> 	   && h->root.plt.plist->comp_offset != MINUS_ONE)
>     {
>       sec = htab->splt;
>       symbol = (sec->output_section->vma
> 		+ sec->output_offset
> 		+ htab->plt_header_size
> 		+ htab->plt_mips_offset
> 		+ h->root.plt.plist->comp_offset
> 		+ 1);
>       target_is_16_bit_code_p = !MICROMIPS_P (abfd);
>       target_is_micromips_code_p = MICROMIPS_P (abfd);
>     }
> 
> at the end of the:
> 
>   /* If this is a reference to a 16-bit function with a stub, we need
>      to redirect the relocation to the stub unless:
> 
> chain of ifs.

 More or less, though I've decided to push it ahead of the chain so that 
it sees the state consistent regardless of whether any PLT entry processed 
has been duplicated for dual-mode support.  This probably does not really 
matter right now (fn_stub/need_fn_stub cases will override any symbol 
value to use for the relocation and likewise the mode setting anyway, 
call_stub/call_fp_stub cases will only ever have a standard MIPS PLT entry 
due to the arrangement in _bfd_mips_elf_adjust_dynamic_symbol and 
la25_stub cases will never have a PLT entry as these must resolve 
locally), but I feel a bit uneasy about this half-cooked state.  Let me 
know if you disagree (and why).

 Also I've decided not to recalculate the symbol's value if what 
mips_elf_set_plt_sym_value worked out is the right thing for compressed 
direct calls too (i.e. there is no standard MIPS PLT entry alternative).

> > -      /* Make room for the .got.plt entry and the R_MIPS_JUMP_SLOT
> > -	 relocation.  */
> > -      htab->sgotplt->size += MIPS_ELF_GOT_SIZE (dynobj);
> > +      htab->splt->size = htab->plt_mips_offset + htab->plt_comp_offset;
> > +      htab->sgotplt->size = htab->plt_got_index * MIPS_ELF_GOT_SIZE (dynobj);
> 
> These last two lines should be done in size_dynamic_sections rather
> than once for each symbol.  I.e.:
> 
> > @@ -8985,18 +9318,60 @@ _bfd_mips_elf_size_dynamic_sections (bfd
> >  	    = (bfd_byte *) ELF_DYNAMIC_INTERPRETER (output_bfd);
> >  	}
> >  
> > -      /* Create a symbol for the PLT, if we know that we are using it.  */
> > -      if (htab->splt && htab->splt->size > 0 && htab->root.hplt == NULL)
> > +      /* Figure out the size of the PLT header if we know that we
> > +         are using it.  For the sake of cache alignment always use
> > +         a standard header whenever any standard entries are present
> > +         even if microMIPS entries are present as well.  This also
> > +         lets the microMIPS header rely on the value of $v0 only set
> > +         by microMIPS entries, for a small size reduction.
> > +
> > +         Set symbol table entry values for symbols that use the
> > +         address of their PLT entry now that we can calculate it.
> > +
> > +         Also create the _PROCEDURE_LINKAGE_TABLE_ symbol if we
> > +         haven't already in _bfd_elf_create_dynamic_sections.  */
> > +      if (htab->splt && htab->splt->size > 0)
> >  	{
> > +	  bfd_boolean micromips_p = (MICROMIPS_P (output_bfd)
> > +				     && !htab->plt_mips_offset);
> > +	  unsigned int other = micromips_p ? STO_MICROMIPS : 0;
> > +	  bfd_vma isa_bit = micromips_p;
> >  	  struct elf_link_hash_entry *h;
> > +	  bfd_vma size;
> >  
> >  	  BFD_ASSERT (htab->use_plts_and_copy_relocs);
> >  
> > -	  h = _bfd_elf_define_linkage_sym (dynobj, info, htab->splt,
> > -					   "_PROCEDURE_LINKAGE_TABLE_");
> > -	  htab->root.hplt = h;
> > -	  if (h == NULL)
> > -	    return FALSE;
> > +	  if (htab->is_vxworks && info->shared)
> > +	    size = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
> > +	  else if (htab->is_vxworks)
> > +	    size = 4 * ARRAY_SIZE (mips_vxworks_exec_plt0_entry);
> > +	  else if (ABI_64_P (output_bfd))
> > +	    size = 4 * ARRAY_SIZE (mips_n64_exec_plt0_entry);
> > +	  else if (ABI_N32_P (output_bfd))
> > +	    size = 4 * ARRAY_SIZE (mips_n32_exec_plt0_entry);
> > +	  else if (!micromips_p)
> > +	    size = 4 * ARRAY_SIZE (mips_o32_exec_plt0_entry);
> > +	  else
> > +	    size = 2 * ARRAY_SIZE (micromips_o32_exec_plt0_entry);
> > +
> > +	  htab->plt_header_is_comp = micromips_p;
> > +	  htab->plt_header_size = size;
> > +	  htab->splt->size += size;
> 
> 	  htab->splt->size = (size
> 			      + htab->plt_mips_offset
> 			      + htab->plt_comp_offset;
> 	  htab->sgotplt->size = (htab->plt_got_index
> 				 * MIPS_ELF_GOT_SIZE (dynobj));

 Sure, I had to adjust the condition around this block:

      if (htab->splt && htab->splt->size > 0)

and one in _bfd_mips_elf_adjust_dynamic_symbol accordingly though.

> > +	      /* ADDIUPC has a span of +/-16MB, check we're in range.  */
> > +	      if (gotpc_offset + 0x1000000 >= 0x2000000)
> > +		{
> > +		  (*_bfd_error_handler)
> > +		    (_("%B: `%A' offset of %ld from `%A' "
> > +		       "beyond the range of ADDIUPC"),
> > +		     output_bfd,
> > +		     htab->sgotplt->output_section,
> > +		     htab->splt->output_section,
> > +		     (long) gotpc_offset);
> 
> The last two arguments should be swapped.

 Nope, %A and %B are handled specially (ahead of any other format 
specifiers).  See the comment at _bfd_default_error_handler in bfd/bfd.c. 
I actually verified this range checking triggers correctly (hmm, it might 
be worth making a dedicated test case for) and it would be outright silly 
to make such a mistake, wouldn't it (hint, hint!)?

> > +      /* ADDIUPC has a span of +/-16MB, check we're in range.  */
> > +      if (gotpc_offset + 0x1000000 >= 0x2000000)
> > +	{
> > +	  (*_bfd_error_handler)
> > +	    (_("%B: `%A' offset of %ld from `%A' beyond the range of ADDIUPC"),
> > +	     output_bfd,
> > +	     htab->sgotplt->output_section,
> > +	     htab->splt->output_section,
> > +	     (long) gotpc_offset);
> 
> Same here.

 Ditto. ;)

> > +  /* Calculating the exact amount of space required for symbols would
> > +     require two passes over the PLT, so just pessimise assuming two
> > +     PLT slots per relocation.  */
> > +  count = relplt->size / hdr->sh_entsize;
> > +  counti = count * bed->s->int_rels_per_ext_rel;
> > +  size = 2 * count * sizeof (asymbol);
> > +  size += count * (sizeof (mipssuffix) +
> > +		   (micromips_p ? sizeof (microsuffix) : sizeof (m16suffix)));
> > +  addlen = 2 * (sizeof ("+0x") - 1 + 8);
> > +#ifdef BFD64
> > +  addlen += 2 * 8 * (bed->s->elfclass == ELFCLASS64);
> > +#endif
> 
> Now that there are no addends (thanks), the last four lines should be dropped.

 Missed that, thanks for catching; I guess a newer GCC version would 
complain about this set-but-unused addlen variable.  Dropped that now as 
well as the variable itself.

> OK with those changes if they work, otherwise let me know.

 Given that (as noted above) the change is more than just what you 
suggested, here's a new version for you to review, in the form of an 
incremental change on top of the previous one (let me know if you'd like 
to see a combined version as well; I've included the intended set of 
ChangeLog entries only).  Please double-check you're all right with it.  
No regressions across the usual set of MIPS targets (let me know if you 
want me to remind you of the actual list).  Thanks.

2013-06-07  Maciej W. Rozycki  <macro@codesourcery.com>

	bfd/
	* elfxx-mips.h (_bfd_mips_elf_get_synthetic_symtab): New
	prototype.
	* elf32-mips.c (elf_backend_plt_sym_val): Remove macro.
	(bfd_elf32_get_synthetic_symtab): New macro.
	* elfxx-mips.c (plt_entry): New structure.
	(mips_elf_link_hash_entry): Add use_plt_entry member.
	(mips_elf_link_hash_table): Rename plt_entry_size member to
	plt_mips_entry_size.  Add plt_comp_entry_size, plt_mips_offset,
	plt_comp_offset, plt_got_index entries and plt_header_is_comp
	members.
	(STUB_LW_MICROMIPS, STUB_MOVE_MICROMIPS): New macros.
	(STUB_LUI_MICROMIPS, STUB_JALR_MICROMIPS): Likewise.
	(STUB_ORI_MICROMIPS, STUB_LI16U_MICROMIPS): Likewise.
	(STUB_LI16S_MICROMIPS): Likewise.
	(MICROMIPS_FUNCTION_STUB_NORMAL_SIZE): Likewise.
	(MICROMIPS_FUNCTION_STUB_BIG_SIZE): Likewise.
	(micromips_o32_exec_plt0_entry): New variable.
	(mips16_o32_exec_plt_entry): Likewise.
	(micromips_o32_exec_plt_entry): Likewise.
	(mips_elf_link_hash_newfunc): Initialize use_plt_entry.
	(mips_elf_output_extsym): Update to use gotplt_union's plist
	member rather than offset.
	(mips_elf_gotplt_index): Likewise.  Remove the VxWorks
	restriction.  Use MIPS_ELF_GOT_SIZE to calculate GOT address.
	(mips_elf_count_got_symbols): Update to use gotplt_union's plist
	member rather than offset.
	(mips_elf_calculate_relocation): Handle MIPS16/microMIPS PLT
	entries.
	(_bfd_mips_elf_create_dynamic_sections): Don't set PLT sizes
	here.
	(mips_elf_make_plt_record): New function.
	(_bfd_mips_elf_check_relocs): Update comment.  Record occurences
	of JAL relocations that might need a PLT entry.
	(_bfd_mips_elf_adjust_dynamic_symbol): Update to use
	gotplt_union's plist member rather than offset.  Set individual
	PLT entry sizes here.  Handle MIPS16/microMIPS PLT entries.
	Don't set the symbol's value in the symbol table for PLT
	references here.  Don't set the PLT or PLT GOT section sizes
	here.
	(mips_elf_estimate_stub_size): Handle microMIPS stubs.
	(mips_elf_allocate_lazy_stub): Likewise.
	(mips_elf_lay_out_lazy_stubs): Likewise.  Define a _MIPS_STUBS_
	magic symbol.
	(mips_elf_set_plt_sym_value): New function.
	(_bfd_mips_elf_size_dynamic_sections): Set PLT header size and
	PLT and PLT GOT section sizes here.  Set the symbol values in
	the symbol table for PLT references here.  Handle microMIPS
	annotation of the _PROCEDURE_LINKAGE_TABLE_ magic symbol.
	(_bfd_mips_elf_finish_dynamic_symbol): Update to use
	gotplt_union's plist member rather than offset.  Handle
	MIPS16/microMIPS PLT entries.  Handle microMIPS stubs.
	(_bfd_mips_vxworks_finish_dynamic_symbol): Update to use
	gotplt_union's plist member rather than offset.  Use
	MIPS_ELF_GOT_SIZE to calculate GOT address.
	(mips_finish_exec_plt): Handle microMIPS PLT.  Return status.
	(_bfd_mips_elf_finish_dynamic_sections): Handle result from
	mips_finish_exec_plt.
	(_bfd_mips_elf_link_hash_table_create): Update to use
	gotplt_union's plist member rather than offset.
	(_bfd_mips_elf_get_synthetic_symtab): New function.

	include/elf/
	* mips.h (ELF_ST_IS_MIPS_PLT): Respect STO_MIPS16 setting.
	(ELF_ST_SET_MIPS_PLT): Likewise.

	gdb/
	* mips-tdep.c (mips_elf_make_msymbol_special): Handle MIPS16 and
	microMIPS synthetic symbols.

	ld/
	* emulparams/elf32btsmip.sh: Arrange for .got.plt to be placed
	as close to .plt as possible.
	* scripttempl/elf.sc: Handle $INITIAL_READWRITE_SECTIONS and
	$PLT_NEXT_DATA variables.

	ld/testsuite/
	* ld-mips-elf/jalx-2.dd: Update for microMIPS PLT support.
	* ld-mips-elf/pic-and-nonpic-3a.dd: Update for the _MIPS_STUBS_
	magic symbol.
	* ld-mips-elf/pic-and-nonpic-3b.dd: Likewise.
	* ld-mips-elf/pic-and-nonpic-6-n32.dd: Likewise.
	* ld-mips-elf/pic-and-nonpic-6-n64.dd: Likewise.
	* ld-mips-elf/pic-and-nonpic-6-o32.dd: Likewise.
	* ld-mips-elf/stub-dynsym-1-10000.d: Likewise.
	* ld-mips-elf/stub-dynsym-1-2fe80.d: Likewise.
	* ld-mips-elf/stub-dynsym-1-7fff.d: Likewise.
	* ld-mips-elf/stub-dynsym-1-8000.d: Likewise.
	* ld-mips-elf/stub-dynsym-1-fff0.d: Likewise.
	* ld-mips-elf/tlslib-o32.d: Likewise.

	opcodes/
	* mips-dis.c (is_mips16_plt_tail): New function.
	(print_insn_mips16): Handle MIPS16 PLT entry's GOT slot address
	word.
	(is_compressed_mode_p): Handle MIPS16/microMIPS PLT entries.

  Maciej

binutils-umips16-plt-stubs-update.diff
Index: binutils-fsf-trunk-quilt/bfd/elfxx-mips.c
===================================================================
--- binutils-fsf-trunk-quilt.orig/bfd/elfxx-mips.c	2013-06-07 19:07:47.000000000 +0100
+++ binutils-fsf-trunk-quilt/bfd/elfxx-mips.c	2013-06-07 21:02:39.942586414 +0100
@@ -318,9 +318,9 @@ struct mips_elf_hash_sort_data
 };
 
 /* We make up to two PLT entries if needed, one for standard MIPS code
-   and one for compressed code, either of MIPS16 or microMIPS one.  We
-   keep the record of a stub if one is used instead separately, for
-   easier processing.  */
+   and one for compressed code, either a MIPS16 or microMIPS one.  We
+   keep a separate record of traditional lazy-binding stubs, for easier
+   processing.  */
 
 struct plt_entry
 {
@@ -5201,9 +5201,6 @@ mips_elf_calculate_relocation (bfd *abfd
       /* Record the name of this symbol, for our caller.  */
       *namep = h->root.root.root.string;
 
-      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
-      target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (h->root.other);
-
       /* See if this is the special _gp_disp symbol.  Note that such a
 	 symbol must always be a global symbol.  */
       if (strcmp (*namep, "_gp_disp") == 0
@@ -5230,55 +5227,13 @@ mips_elf_calculate_relocation (bfd *abfd
 		|| h->root.root.type == bfd_link_hash_defweak)
 	       && h->root.root.u.def.section)
 	{
-	  if (h->use_plt_entry)
-	    {
-	      bfd_boolean micromips_p = MICROMIPS_P (abfd);
-	      bfd_vma plt_offset;
-	      bfd_vma isa_bit;
-	      bfd_vma val;
-
-	      BFD_ASSERT (h->root.plt.plist != NULL);
-	      BFD_ASSERT (h->root.plt.plist->mips_offset != MINUS_ONE
-			  || h->root.plt.plist->comp_offset != MINUS_ONE);
-
-	      plt_offset = htab->plt_header_size;
-	      if (h->root.plt.plist->comp_offset == MINUS_ONE
-		  || (h->root.plt.plist->mips_offset != MINUS_ONE
-		      && r_type != R_MIPS16_26 && r_type != R_MICROMIPS_26_S1))
-		{
-		  isa_bit = 0;
-		  target_is_16_bit_code_p = FALSE;
-		  target_is_micromips_code_p = FALSE;
-		  plt_offset += h->root.plt.plist->mips_offset;
-		}
-	      else
-		{
-		  isa_bit = 1;
-		  target_is_16_bit_code_p = !micromips_p;
-		  target_is_micromips_code_p = micromips_p;
-		  plt_offset += (htab->plt_mips_offset
-				 + h->root.plt.plist->comp_offset);
-		}
-	      BFD_ASSERT (plt_offset <= htab->splt->size);
-
-	      sec = htab->splt;
-	      val = plt_offset + isa_bit;
-	      /* For VxWorks, point at the PLT load stub rather than the
-	         lazy resolution stub.  */
-	      if (htab->is_vxworks)
-		val += 8;
-	      symbol = sec->output_section->vma + sec->output_offset + val;
-	    }
+	  sec = h->root.root.u.def.section;
+	  if (sec->output_section)
+	    symbol = (h->root.root.u.def.value
+		      + sec->output_section->vma
+		      + sec->output_offset);
 	  else
-	    {
-	      sec = h->root.root.u.def.section;
-	      if (sec->output_section)
-		symbol = (h->root.root.u.def.value
-			  + sec->output_section->vma
-			  + sec->output_offset);
-	      else
-		symbol = h->root.root.u.def.value;
-	    }
+	    symbol = h->root.root.u.def.value;
 	}
       else if (h->root.root.type == bfd_link_hash_undefweak)
 	/* We allow relocations against undefined weak symbols, giving
@@ -5325,6 +5280,35 @@ mips_elf_calculate_relocation (bfd *abfd
 	{
 	  return bfd_reloc_notsupported;
 	}
+
+      target_is_16_bit_code_p = ELF_ST_IS_MIPS16 (h->root.other);
+      target_is_micromips_code_p = ELF_ST_IS_MICROMIPS (h->root.other);
+    }
+
+  /* For direct MIPS16 and microMIPS calls make sure the compressed PLT
+     entry is used if a standard PLT entry has also been made.  In this
+     case the symbol will have been set by mips_elf_set_plt_sym_value
+     to point to the standard PLT entry, so redirect to the compressed
+     one.  Adjust the mode settings accordingly.  */
+  if ((r_type == R_MIPS16_26 || r_type == R_MICROMIPS_26_S1)
+      && !info->relocatable
+      && h != NULL
+      && h->use_plt_entry
+      && h->root.plt.plist->comp_offset != MINUS_ONE
+      && h->root.plt.plist->mips_offset != MINUS_ONE)
+    {
+      bfd_boolean micromips_p = MICROMIPS_P (abfd);
+
+      sec = htab->splt;
+      symbol = (sec->output_section->vma
+		+ sec->output_offset
+		+ htab->plt_header_size
+		+ htab->plt_mips_offset
+		+ h->root.plt.plist->comp_offset
+		+ 1);
+
+      target_is_16_bit_code_p = !micromips_p;
+      target_is_micromips_code_p = micromips_p;
     }
 
   /* If this is a reference to a 16-bit function with a stub, we need
@@ -8778,7 +8762,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
       /* If this is the first symbol to need a PLT entry, then make some
          basic setup.  Also work out PLT entry sizes.  We'll need them
          for PLT offset calculations.  */
-      if (htab->splt->size == 0)
+      if (htab->plt_mips_offset + htab->plt_comp_offset == 0)
 	{
 	  BFD_ASSERT (htab->sgotplt->size == 0);
 	  BFD_ASSERT (htab->plt_got_index == 0);
@@ -8890,9 +8874,6 @@ _bfd_mips_elf_adjust_dynamic_symbol (str
       if (!info->shared && !h->def_regular)
 	hmips->use_plt_entry = TRUE;
 
-      htab->splt->size = htab->plt_mips_offset + htab->plt_comp_offset;
-      htab->sgotplt->size = htab->plt_got_index * MIPS_ELF_GOT_SIZE (dynobj);
-
       /* Make room for the R_MIPS_JUMP_SLOT relocation.  */
       htab->srelplt->size += (htab->is_vxworks
 			      ? MIPS_ELF_RELA_SIZE (dynobj)
@@ -9338,7 +9319,7 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 
          Also create the _PROCEDURE_LINKAGE_TABLE_ symbol if we
          haven't already in _bfd_elf_create_dynamic_sections.  */
-      if (htab->splt && htab->splt->size > 0)
+      if (htab->splt && htab->plt_mips_offset + htab->plt_comp_offset != 0)
 	{
 	  bfd_boolean micromips_p = (MICROMIPS_P (output_bfd)
 				     && !htab->plt_mips_offset);
@@ -9348,6 +9329,8 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 	  bfd_vma size;
 
 	  BFD_ASSERT (htab->use_plts_and_copy_relocs);
+	  BFD_ASSERT (htab->sgotplt->size == 0);
+	  BFD_ASSERT (htab->splt->size == 0);
 
 	  if (htab->is_vxworks && info->shared)
 	    size = 4 * ARRAY_SIZE (mips_vxworks_shared_plt0_entry);
@@ -9364,7 +9347,11 @@ _bfd_mips_elf_size_dynamic_sections (bfd
 
 	  htab->plt_header_is_comp = micromips_p;
 	  htab->plt_header_size = size;
-	  htab->splt->size += size;
+	  htab->splt->size = (size
+			      + htab->plt_mips_offset
+			      + htab->plt_comp_offset);
+	  htab->sgotplt->size = (htab->plt_got_index
+				 * MIPS_ELF_GOT_SIZE (dynobj));
 
 	  mips_elf_link_hash_traverse (htab, mips_elf_set_plt_sym_value, info);
 
@@ -14943,7 +14930,6 @@ _bfd_mips_elf_get_synthetic_symtab (bfd 
   bfd_vma opcode;
   asection *plt;
   asymbol *send;
-  size_t addlen;
   size_t size;
   char *names;
   long counti;
@@ -14985,10 +14971,6 @@ _bfd_mips_elf_get_synthetic_symtab (bfd 
   size = 2 * count * sizeof (asymbol);
   size += count * (sizeof (mipssuffix) +
 		   (micromips_p ? sizeof (microsuffix) : sizeof (m16suffix)));
-  addlen = 2 * (sizeof ("+0x") - 1 + 8);
-#ifdef BFD64
-  addlen += 2 * 8 * (bed->s->elfclass == ELFCLASS64);
-#endif
   for (pi = 0; pi < counti; pi += bed->s->int_rels_per_ext_rel)
     size += 2 * strlen ((*p[pi].sym_ptr_ptr)->name);
 
Index: binutils-fsf-trunk-quilt/include/elf/mips.h
===================================================================
--- binutils-fsf-trunk-quilt.orig/include/elf/mips.h	2013-06-07 19:06:39.000000000 +0100
+++ binutils-fsf-trunk-quilt/include/elf/mips.h	2013-06-07 19:07:49.052856391 +0100
@@ -803,8 +803,14 @@ extern void bfd_mips_elf32_swap_reginfo_
    PLT entries and traditional MIPS lazy binding stubs.  We mark the former
    with STO_MIPS_PLT to distinguish them from the latter.  */
 #define STO_MIPS_PLT		0x8
-#define ELF_ST_IS_MIPS_PLT(other) (((other) & STO_MIPS_FLAGS) == STO_MIPS_PLT)
-#define ELF_ST_SET_MIPS_PLT(other) (((other) & ~STO_MIPS_FLAGS) | STO_MIPS_PLT)
+#define ELF_ST_IS_MIPS_PLT(other)					\
+  ((ELF_ST_IS_MIPS16 (other)						\
+    ? ((other) & (~STO_MIPS16 & STO_MIPS_FLAGS))			\
+    : ((other) & STO_MIPS_FLAGS)) == STO_MIPS_PLT)
+#define ELF_ST_SET_MIPS_PLT(other)					\
+  ((ELF_ST_IS_MIPS16 (other)						\
+    ? ((other) & (STO_MIPS16 | ~STO_MIPS_FLAGS))			\
+    : ((other) & ~STO_MIPS_FLAGS)) | STO_MIPS_PLT)
 
 /* This value is used to mark PIC functions in an object that mixes
    PIC and non-PIC.  Note that this bit overlaps with STO_MIPS16,



More information about the Gdb-patches mailing list