[PATCH] Support more sparc relocs

David Miller davem@davemloft.net
Wed Apr 11 19:50:00 GMT 2012


From: David Miller <davem@davemloft.net>
Date: Sat, 07 Apr 2012 10:46:28 -0400 (EDT)

Ping for the non-Gold parts?

> This adds support for R_SPARC_H34 and R_SPARC_WDISP10.
> 
> R_SPARC_H34 is used for a 34-bit absolute code model,
> basically accesses look like this:
> 
> 	sethi	%h34(symbol), %g1
> 	sllx	%g1, 2, %g1
> 	or	%g1, %l34(symbol), %g1
> 
> or:
> 
> 	sethi	%h34(symbol), %g1
> 	sllx	%g1, 2, %g1
> 	ld	[%g1 + %l34(symbol)], %g1
> 
> Note that an explicit R_SPARC_L34 was not created, we simply use
> R_SPARC_L44 since that makes the calculate we want.  I've added
> entries to sparc's reloc64 test case to cover this.
> 
> R_SPARC_WDISP10 will be used in support for newer instructions in an
> upcoming set of changes.  I'll add test cases for this relocation
> when I add those instructions.
> 
> You may notice that I added the R_SPARC_32/R_SPARC_64 entries to the
> sparc BFD howto table.  This was to simplify the indexing of
> R_SPARC_H34 and R_SPARC_WDISP10.  If I didn't add the
> R_SPARC_32/R_SPARC_64 entries I'd have to add seperate howto objects
> outside of the array which would be ugly and really not necessary.
> 
> I plan to add proper R_SPARC_32 and R_SPARC_64 support some time
> soon.
> 
> Ok to commit?
> 
> include/
> 
> 	* elf/sparc.h (R_SPARC_WDISP10): New reloc.
> 	* opcode/sparc.h: Define '=' as generating R_SPARC_WDISP10.
> 
> opcodes/
> 
> 	* sparc-dis.c (X_DISP10): Define.
> 	(print_insn_sparc): Handle '='.
> 
> bfd/
> 
> 	* reloc.c (BFD_RELOC_SPARC_H34, BFD_RELOC_SPARC_SIZE32,
> 	BFD_RELOC_SPARC_SIZE64, BFD_RELOC_SPARC_WDISP10): New relocs.
> 	* libbfd.h: Regenerate.
> 	* bfd-in2.h: Likewise.
> 	* elfxx-sparc.c (sparc_elf_wdisp10_reloc): New function.
> 	(_bfd_sparc_elf_howto_table): Add entries for R_SPARC_H34,
> 	R_SPARC_SIZE32, R_SPARC_64, and R_SPARC_WDISP10.
> 	(_bfd_sparc_elf_reloc_type_lookup): Handle new relocs.
> 	(_bfd_sparc_elf_check_relocs): Likewise.
> 	(_bfd_sparc_elf_gc_sweep_hook): Likewise.
> 	(_bfd_sparc_elf_relocate_section): Likewise.
> 
> gas/
> 
> 	* config/tc-sparc.c (sparc_ip): Handle '=', "%h34", "%l34", and
> 	BFD_RELOC_SPARC_H34.
> 	(md_apply_fix): Handle BFD_RELOC_SPARC_WDISP10 and BFD_RELOC_SPARC_H34.
> 	(tc_gen_reloc): Likewise.
> 
> gas/testsuite/
> 
> 	* gas/sparc/reloc64.s: Add abs34 code model tests.
> 	* gas/sparc/reloc64.d: Update.
> 
> elfcpp/
> 
> 	* sparc.h (R_SPARC_WDISP10): New relocation.
> 
> gold/
> 
> 	* sparc.cc (Reloc::wdisp10): New relocation method.
> 	(Reloc::h34): Likewise.
> 	(Target_sparc::Scan::check_non_pic): Handle R_SPARC_H34.
> 	(Target_sparc::Scan::get_reference_flags): Handle R_SPARC_H34 and
> 	R_SPARC_WDISP10.
> 	(Target_sparc::Scan::local): Likewise.
> 	(Target_sparc::Scan::global): Likewise.
> 	(Target_sparc::Relocate::relocate): Likewise.
> 
> diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
> index 07898be..859f825 100644
> --- a/bfd/bfd-in2.h
> +++ b/bfd/bfd-in2.h
> @@ -2595,6 +2595,10 @@ relocation types already defined.  */
>    BFD_RELOC_SPARC_M44,
>    BFD_RELOC_SPARC_L44,
>    BFD_RELOC_SPARC_REGISTER,
> +  BFD_RELOC_SPARC_H34,
> +  BFD_RELOC_SPARC_SIZE32,
> +  BFD_RELOC_SPARC_SIZE64,
> +  BFD_RELOC_SPARC_WDISP10,
>  
>  /* SPARC little endian relocation  */
>    BFD_RELOC_SPARC_REV32,
> diff --git a/bfd/elfxx-sparc.c b/bfd/elfxx-sparc.c
> index 9155311..9609d37 100644
> --- a/bfd/elfxx-sparc.c
> +++ b/bfd/elfxx-sparc.c
> @@ -132,6 +132,34 @@ sparc_elf_wdisp16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
>      return bfd_reloc_ok;
>  }
>  
> +/* Handle the WDISP10 reloc.  */
> +
> +static bfd_reloc_status_type
> +sparc_elf_wdisp10_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol,
> +			 PTR data, asection *input_section, bfd *output_bfd,
> +			 char **error_message ATTRIBUTE_UNUSED)
> +{
> +  bfd_vma relocation;
> +  bfd_vma insn;
> +  bfd_reloc_status_type status;
> +
> +  status = init_insn_reloc (abfd, reloc_entry, symbol, data,
> +			    input_section, output_bfd, &relocation, &insn);
> +  if (status != bfd_reloc_other)
> +    return status;
> +
> +  insn &= ~ (bfd_vma) 0x181fe0;
> +  insn |= (((relocation >> 2) & 0x300) << 11)
> +	  | (((relocation >> 2) & 0xff) << 5);
> +  bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
> +
> +  if ((bfd_signed_vma) relocation < - 0x1000
> +      || (bfd_signed_vma) relocation > 0xfff)
> +    return bfd_reloc_overflow;
> +  else
> +    return bfd_reloc_ok;
> +}
> +
>  /* Handle the HIX22 reloc.  */
>  
>  static bfd_reloc_status_type
> @@ -267,6 +295,10 @@ static reloc_howto_type _bfd_sparc_elf_howto_table[] =
>    HOWTO(R_SPARC_GOTDATA_OP_HIX22,0,2,0,FALSE,0,complain_overflow_bitfield,sparc_elf_hix22_reloc,"R_SPARC_GOTDATA_OP_HIX22",FALSE,0,0x003fffff, FALSE),
>    HOWTO(R_SPARC_GOTDATA_OP_LOX10,0,2,0,FALSE,0,complain_overflow_dont,  sparc_elf_lox10_reloc,  "R_SPARC_GOTDATA_OP_LOX10",FALSE,0,0x000003ff, FALSE),
>    HOWTO(R_SPARC_GOTDATA_OP,0,0, 0,FALSE,0,complain_overflow_dont,   bfd_elf_generic_reloc,  "R_SPARC_GOTDATA_OP",FALSE,0,0x00000000,TRUE),
> +  HOWTO(R_SPARC_H34,12,2,22,FALSE,0,complain_overflow_unsigned,bfd_elf_generic_reloc,"R_SPARC_H34",FALSE,0,0x003fffff,FALSE),
> +  HOWTO(R_SPARC_SIZE32,0,2,32,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE32",FALSE,0,0xffffffff,TRUE),
> +  HOWTO(R_SPARC_SIZE64,0,4,64,FALSE,0,complain_overflow_bitfield,bfd_elf_generic_reloc,"R_SPARC_SIZE64",FALSE,0,MINUS_ONE, TRUE),
> +  HOWTO(R_SPARC_WDISP10,2,2,10,TRUE, 0,complain_overflow_signed,sparc_elf_wdisp10_reloc,"R_SPARC_WDISP10",FALSE,0,0x00000000,TRUE),
>  };
>  static reloc_howto_type sparc_jmp_irel_howto =
>    HOWTO(R_SPARC_JMP_IREL,  0,0,00,FALSE,0,complain_overflow_dont,    bfd_elf_generic_reloc,  "R_SPARC_JMP_IREL",FALSE,0,0x00000000,TRUE);
> @@ -524,6 +556,18 @@ _bfd_sparc_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
>      case BFD_RELOC_SPARC_GOTDATA_OP:
>        return &_bfd_sparc_elf_howto_table[R_SPARC_GOTDATA_OP];
>  
> +    case BFD_RELOC_SPARC_H34:
> +      return &_bfd_sparc_elf_howto_table[R_SPARC_H34];
> +
> +    case BFD_RELOC_SPARC_SIZE32:
> +      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE32];
> +
> +    case BFD_RELOC_SPARC_SIZE64:
> +      return &_bfd_sparc_elf_howto_table[R_SPARC_SIZE64];
> +
> +    case BFD_RELOC_SPARC_WDISP10:
> +      return &_bfd_sparc_elf_howto_table[R_SPARC_WDISP10];
> +
>      case BFD_RELOC_SPARC_JMP_IREL:
>        return &sparc_jmp_irel_howto;
>  
> @@ -1656,6 +1700,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>  	case R_SPARC_WDISP22:
>  	case R_SPARC_WDISP19:
>  	case R_SPARC_WDISP16:
> +	case R_SPARC_WDISP10:
>  	case R_SPARC_8:
>  	case R_SPARC_16:
>  	case R_SPARC_32:
> @@ -1680,6 +1725,7 @@ _bfd_sparc_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>  	case R_SPARC_H44:
>  	case R_SPARC_M44:
>  	case R_SPARC_L44:
> +	case R_SPARC_H34:
>  	case R_SPARC_UA64:
>  	  if (h != NULL)
>  	    h->non_got_ref = 1;
> @@ -1956,6 +2002,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
>  	case R_SPARC_WDISP22:
>  	case R_SPARC_WDISP19:
>  	case R_SPARC_WDISP16:
> +	case R_SPARC_WDISP10:
>  	case R_SPARC_8:
>  	case R_SPARC_16:
>  	case R_SPARC_32:
> @@ -1981,6 +2028,7 @@ _bfd_sparc_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
>  	case R_SPARC_H44:
>  	case R_SPARC_M44:
>  	case R_SPARC_L44:
> +	case R_SPARC_H34:
>  	case R_SPARC_UA64:
>  	  if (info->shared)
>  	    break;
> @@ -3276,6 +3324,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
>  	case R_SPARC_WDISP22:
>  	case R_SPARC_WDISP19:
>  	case R_SPARC_WDISP16:
> +	case R_SPARC_WDISP10:
>  	case R_SPARC_8:
>  	case R_SPARC_16:
>  	case R_SPARC_32:
> @@ -3300,6 +3349,7 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
>  	case R_SPARC_H44:
>  	case R_SPARC_M44:
>  	case R_SPARC_L44:
> +	case R_SPARC_H34:
>  	case R_SPARC_UA64:
>  	r_sparc_plt32:
>  	  if ((input_section->flags & SEC_ALLOC) == 0
> @@ -3871,6 +3921,25 @@ _bfd_sparc_elf_relocate_section (bfd *output_bfd,
>  				  bfd_arch_bits_per_address (input_bfd),
>  				  relocation);
>  	}
> +      else if (r_type == R_SPARC_WDISP10)
> +	{
> +	  bfd_vma x;
> +
> +	  relocation += rel->r_addend;
> +	  relocation -= (input_section->output_section->vma
> +			 + input_section->output_offset);
> +	  relocation -= rel->r_offset;
> +
> +	  x = bfd_get_32 (input_bfd, contents + rel->r_offset);
> +	  x |= ((((relocation >> 2) & 0x300) << 11)
> +		| (((relocation >> 2) & 0xff) << 5));
> +	  bfd_put_32 (input_bfd, x, contents + rel->r_offset);
> +
> +	  r = bfd_check_overflow (howto->complain_on_overflow,
> +				  howto->bitsize, howto->rightshift,
> +				  bfd_arch_bits_per_address (input_bfd),
> +				  relocation);
> +	}
>        else if (r_type == R_SPARC_REV32)
>  	{
>  	  bfd_vma x;
> diff --git a/bfd/libbfd.h b/bfd/libbfd.h
> index 844d3a7..cc293bc 100644
> --- a/bfd/libbfd.h
> +++ b/bfd/libbfd.h
> @@ -1014,6 +1014,10 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
>    "BFD_RELOC_SPARC_M44",
>    "BFD_RELOC_SPARC_L44",
>    "BFD_RELOC_SPARC_REGISTER",
> +  "BFD_RELOC_SPARC_H34",
> +  "BFD_RELOC_SPARC_SIZE32",
> +  "BFD_RELOC_SPARC_SIZE64",
> +  "BFD_RELOC_SPARC_WDISP10",
>    "BFD_RELOC_SPARC_REV32",
>    "BFD_RELOC_SPARC_TLS_GD_HI22",
>    "BFD_RELOC_SPARC_TLS_GD_LO10",
> diff --git a/bfd/reloc.c b/bfd/reloc.c
> index fb3aab2..aed3612 100644
> --- a/bfd/reloc.c
> +++ b/bfd/reloc.c
> @@ -1942,6 +1942,14 @@ ENUMX
>    BFD_RELOC_SPARC_L44
>  ENUMX
>    BFD_RELOC_SPARC_REGISTER
> +ENUMX
> +  BFD_RELOC_SPARC_H34
> +ENUMX
> +  BFD_RELOC_SPARC_SIZE32
> +ENUMX
> +  BFD_RELOC_SPARC_SIZE64
> +ENUMX
> +  BFD_RELOC_SPARC_WDISP10
>  ENUMDOC
>    SPARC64 relocations
>  
> diff --git a/elfcpp/sparc.h b/elfcpp/sparc.h
> index 6a9193b..77c4668 100644
> --- a/elfcpp/sparc.h
> +++ b/elfcpp/sparc.h
> @@ -140,6 +140,7 @@ enum
>    R_SPARC_H34 = 85,           // Direct high 12 of 34 bit
>    R_SPARC_SIZE32 = 86,        // size of symbol, 32-bit
>    R_SPARC_SIZE64 = 87,        // size of symbol, 64-bit
> +  R_SPARC_WDISP10 = 88,       // PC relative 10 bit shifted
>  
>    R_SPARC_IRELATIVE = 249,    // Adjust indirectly by program base
>  
> diff --git a/gas/config/tc-sparc.c b/gas/config/tc-sparc.c
> index f453733..1956dff 100644
> --- a/gas/config/tc-sparc.c
> +++ b/gas/config/tc-sparc.c
> @@ -1835,6 +1835,11 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
>  	      the_insn.pcrel = 1;
>  	      goto immediate;
>  
> +	    case '=':
> +	      the_insn.reloc = /* RELOC_WDISP2_8 */ BFD_RELOC_SPARC_WDISP10;
> +	      the_insn.pcrel = 1;
> +	      goto immediate;
> +
>  	    case 'G':
>  	      the_insn.reloc = BFD_RELOC_SPARC_WDISP19;
>  	      the_insn.pcrel = 1;
> @@ -2418,6 +2423,8 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
>  		      { "hh", 2, BFD_RELOC_SPARC_HH22, 1, 1 },
>  		      { "hm", 2, BFD_RELOC_SPARC_HM10, 1, 1 },
>  		      { "lm", 2, BFD_RELOC_SPARC_LM22, 1, 1 },
> +		      { "h34", 3, BFD_RELOC_SPARC_H34, 1, 0 },
> +		      { "l34", 3, BFD_RELOC_SPARC_L44, 1, 0 },
>  		      { "h44", 3, BFD_RELOC_SPARC_H44, 1, 0 },
>  		      { "m44", 3, BFD_RELOC_SPARC_M44, 1, 0 },
>  		      { "l44", 3, BFD_RELOC_SPARC_L44, 1, 0 },
> @@ -2581,6 +2588,11 @@ sparc_ip (char *str, const struct sparc_opcode **pinsn)
>  			    val &= 0x3ff;
>  			    break;
>  
> +			  case BFD_RELOC_SPARC_H34:
> +			    val >>= 12;
> +			    val &= 0x3fffff;
> +			    break;
> +
>  			  case BFD_RELOC_SPARC_H44:
>  			    val >>= 22;
>  			    val &= 0x3fffff;
> @@ -3360,6 +3372,18 @@ md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
>  	  insn |= val & 0x1f;
>  	  break;
>  
> +	case BFD_RELOC_SPARC_WDISP10:
> +	  if ((val & 3)
> +	      || val >= 0x007fc
> +	      || val <= -(offsetT) 0x808)
> +	    as_bad_where (fixP->fx_file, fixP->fx_line,
> +			  _("relocation overflow"));
> +	  /* FIXME: The +1 deserves a comment.  */
> +	  val = (val >> 2) + 1;
> +	  insn |= ((val & 0x300) << 11)
> +	    | ((val & 0xff) << 5);
> +	  break;
> +
>  	case BFD_RELOC_SPARC_WDISP16:
>  	  if ((val & 3)
>  	      || val >= 0x1fffc
> @@ -3433,6 +3457,15 @@ md_apply_fix (fixS *fixP, valueT *valP, segT segment ATTRIBUTE_UNUSED)
>  	  insn |= val & 0x3fffff;
>  	  break;
>  
> +	case BFD_RELOC_SPARC_H34:
> +	  if (!fixP->fx_addsy)
> +	    {
> +	      bfd_vma tval = val;
> +	      tval >>= 12;
> +	      insn |= tval & 0x3fffff;
> +	    }
> +	  break;
> +
>  	case BFD_RELOC_SPARC_H44:
>  	  if (!fixP->fx_addsy)
>  	    {
> @@ -3513,6 +3546,7 @@ tc_gen_reloc (asection *section, fixS *fixp)
>      case BFD_RELOC_SPARC_PC22:
>      case BFD_RELOC_SPARC_PC10:
>      case BFD_RELOC_SPARC_BASE13:
> +    case BFD_RELOC_SPARC_WDISP10:
>      case BFD_RELOC_SPARC_WDISP16:
>      case BFD_RELOC_SPARC_WDISP19:
>      case BFD_RELOC_SPARC_WDISP22:
> @@ -3528,6 +3562,7 @@ tc_gen_reloc (asection *section, fixS *fixp)
>      case BFD_RELOC_SPARC_PC_HH22:
>      case BFD_RELOC_SPARC_PC_HM10:
>      case BFD_RELOC_SPARC_PC_LM22:
> +    case BFD_RELOC_SPARC_H34:
>      case BFD_RELOC_SPARC_H44:
>      case BFD_RELOC_SPARC_M44:
>      case BFD_RELOC_SPARC_L44:
> @@ -3683,6 +3718,7 @@ tc_gen_reloc (asection *section, fixS *fixp)
>        && code != BFD_RELOC_SPARC_WDISP22
>        && code != BFD_RELOC_SPARC_WDISP16
>        && code != BFD_RELOC_SPARC_WDISP19
> +      && code != BFD_RELOC_SPARC_WDISP10
>        && code != BFD_RELOC_SPARC_WPLT30
>        && code != BFD_RELOC_SPARC_TLS_GD_CALL
>        && code != BFD_RELOC_SPARC_TLS_LDM_CALL)
> diff --git a/gas/testsuite/gas/sparc/reloc64.d b/gas/testsuite/gas/sparc/reloc64.d
> index da40d0c..07e2a10 100644
> --- a/gas/testsuite/gas/sparc/reloc64.d
> +++ b/gas/testsuite/gas/sparc/reloc64.d
> @@ -74,3 +74,9 @@ Disassembly of section .text:
>    ac:	82 18 60 00 	xor  %g1, 0, %g1
>  			ac: R_SPARC_LOX10	.text\+0xffffffff76543210
>    b0:	01 00 00 00 	nop 
> +  b4:	03 00 00 00 	sethi  %hi\((0x|)0\), %g1
> +			b4: R_SPARC_H34	.text\+0xa9876543210
> +  b8:	83 28 70 02 	sllx  %g1, 2, %g1
> +  bc:	82 10 60 00 	mov  %g1, %g1
> +			bc: R_SPARC_L44	.text\+0xa9876543210
> +  c0:	01 00 00 00 	nop 
> diff --git a/gas/testsuite/gas/sparc/reloc64.s b/gas/testsuite/gas/sparc/reloc64.s
> index 9ead6af..534a0ae 100644
> --- a/gas/testsuite/gas/sparc/reloc64.s
> +++ b/gas/testsuite/gas/sparc/reloc64.s
> @@ -46,3 +46,7 @@ foo:
>  	sethi %hix(foo+0xffffffff76543210),%g1
>  	xor %g1,%lox(foo+0xffffffff76543210),%g1
>  	nop
> +	sethi %h34(foo+0xa9876543210),%g1
> +	sllx %g1, 2, %g1
> +	or %g1,%l34(foo+0xa9876543210),%g1
> +	nop
> diff --git a/gold/sparc.cc b/gold/sparc.cc
> index 39c7e7c..ee82367 100644
> --- a/gold/sparc.cc
> +++ b/gold/sparc.cc
> @@ -617,6 +617,29 @@ public:
>      elfcpp::Swap<32, true>::writeval(wv, val | reloc);
>    }
>  
> +  // R_SPARC_WDISP10: (Symbol + Addend - Address) >> 2
> +  static inline void
> +  wdisp10(unsigned char* view,
> +	  const Sized_relobj_file<size, big_endian>* object,
> +	  const Symbol_value<size>* psymval,
> +	  typename elfcpp::Elf_types<size>::Elf_Addr addend,
> +	  typename elfcpp::Elf_types<size>::Elf_Addr address)
> +  {
> +    typedef typename elfcpp::Swap<32, true>::Valtype Valtype;
> +    Valtype* wv = reinterpret_cast<Valtype*>(view);
> +    Valtype val = elfcpp::Swap<32, true>::readval(wv);
> +    Valtype reloc = ((psymval->value(object, addend) - address)
> +		     >> 2);
> +
> +    // The relocation value is split between the low bits 5-12,
> +    // and high bits 19-20.
> +    val &= ~((0x3 << 19) | (0xff << 5));
> +    reloc = (((reloc & 0x300) << (19 - 8))
> +	     | ((reloc & 0xff) << (5 - 0)));
> +
> +    elfcpp::Swap<32, true>::writeval(wv, val | reloc);
> +  }
> +
>    // R_SPARC_PC22: (Symbol + Addend - Address) >> 10
>    static inline void
>    pc22(unsigned char* view,
> @@ -832,6 +855,16 @@ public:
>  					addend, address);
>    }
>  
> +  // R_SPARC_H34: (Symbol + Addend) >> 12
> +  static inline void
> +  h34(unsigned char* view,
> +      const Sized_relobj_file<size, big_endian>* object,
> +      const Symbol_value<size>* psymval,
> +      typename elfcpp::Elf_types<size>::Elf_Addr  addend)
> +  {
> +    This_insn::template rela<32>(view, 12, 0x003fffff, object, psymval, addend);
> +  }
> +
>    // R_SPARC_H44: (Symbol + Addend) >> 22
>    static inline void
>    h44(unsigned char* view,
> @@ -1605,6 +1638,7 @@ Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
>      case elfcpp::R_SPARC_64:
>      case elfcpp::R_SPARC_HIX22:
>      case elfcpp::R_SPARC_LOX10:
> +    case elfcpp::R_SPARC_H34:
>      case elfcpp::R_SPARC_H44:
>      case elfcpp::R_SPARC_M44:
>      case elfcpp::R_SPARC_L44:
> @@ -1639,6 +1673,7 @@ Target_sparc<size, big_endian>::Scan::get_reference_flags(unsigned int r_type)
>      case elfcpp::R_SPARC_WDISP22:
>      case elfcpp::R_SPARC_WDISP19:
>      case elfcpp::R_SPARC_WDISP16:
> +    case elfcpp::R_SPARC_WDISP10:
>        return Symbol::RELATIVE_REF;
>  
>      case elfcpp::R_SPARC_PLT64:
> @@ -1755,6 +1790,7 @@ Target_sparc<size, big_endian>::Scan::check_non_pic(Relobj* object, unsigned int
>  	case elfcpp::R_SPARC_LO10:
>  	case elfcpp::R_SPARC_HI22:
>  	case elfcpp::R_SPARC_OLO10:
> +	case elfcpp::R_SPARC_H34:
>  	case elfcpp::R_SPARC_H44:
>  	case elfcpp::R_SPARC_M44:
>  	case elfcpp::R_SPARC_L44:
> @@ -1861,6 +1897,7 @@ Target_sparc<size, big_endian>::Scan::local(
>  
>      case elfcpp::R_SPARC_HIX22:
>      case elfcpp::R_SPARC_LOX10:
> +    case elfcpp::R_SPARC_H34:
>      case elfcpp::R_SPARC_H44:
>      case elfcpp::R_SPARC_M44:
>      case elfcpp::R_SPARC_L44:
> @@ -1911,6 +1948,7 @@ Target_sparc<size, big_endian>::Scan::local(
>      case elfcpp::R_SPARC_WDISP22:
>      case elfcpp::R_SPARC_WDISP19:
>      case elfcpp::R_SPARC_WDISP16:
> +    case elfcpp::R_SPARC_WDISP10:
>      case elfcpp::R_SPARC_DISP8:
>      case elfcpp::R_SPARC_DISP16:
>      case elfcpp::R_SPARC_DISP32:
> @@ -2186,6 +2224,7 @@ Target_sparc<size, big_endian>::Scan::global(
>      case elfcpp::R_SPARC_WDISP22:
>      case elfcpp::R_SPARC_WDISP19:
>      case elfcpp::R_SPARC_WDISP16:
> +    case elfcpp::R_SPARC_WDISP10:
>        {
>  	if (gsym->needs_plt_entry())
>  	  target->make_plt_entry(symtab, layout, gsym);
> @@ -2214,6 +2253,7 @@ Target_sparc<size, big_endian>::Scan::global(
>      case elfcpp::R_SPARC_64:
>      case elfcpp::R_SPARC_HIX22:
>      case elfcpp::R_SPARC_LOX10:
> +    case elfcpp::R_SPARC_H34:
>      case elfcpp::R_SPARC_H44:
>      case elfcpp::R_SPARC_M44:
>      case elfcpp::R_SPARC_L44:
> @@ -2749,6 +2789,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
>        Reloc::wdisp16(view, object, psymval, addend, address);
>        break;
>  
> +    case elfcpp::R_SPARC_WDISP10:
> +      Reloc::wdisp10(view, object, psymval, addend, address);
> +      break;
> +
>      case elfcpp::R_SPARC_HI22:
>        Reloc::hi22(view, object, psymval, addend);
>        break;
> @@ -2900,6 +2944,10 @@ Target_sparc<size, big_endian>::Relocate::relocate(
>        Reloc::lox10(view, object, psymval, addend);
>        break;
>  
> +    case elfcpp::R_SPARC_H34:
> +      Reloc::h34(view, object, psymval, addend);
> +      break;
> +
>      case elfcpp::R_SPARC_H44:
>        Reloc::h44(view, object, psymval, addend);
>        break;
> diff --git a/include/elf/sparc.h b/include/elf/sparc.h
> index fc8a765..880ead6 100644
> --- a/include/elf/sparc.h
> +++ b/include/elf/sparc.h
> @@ -162,6 +162,7 @@ START_RELOC_NUMBERS (elf_sparc_reloc_type)
>    RELOC_NUMBER (R_SPARC_H34, 85)
>    RELOC_NUMBER (R_SPARC_SIZE32, 86)
>    RELOC_NUMBER (R_SPARC_SIZE64, 87)
> +  RELOC_NUMBER (R_SPARC_WDISP10, 88)
>    
>    EMPTY_RELOC  (R_SPARC_max_std)
>  
> diff --git a/include/opcode/sparc.h b/include/opcode/sparc.h
> index 7ae3641..91dc696 100644
> --- a/include/opcode/sparc.h
> +++ b/include/opcode/sparc.h
> @@ -208,7 +208,8 @@ typedef struct sparc_opcode
>  	0	32/64 bit immediate for set or setx (v9) insns
>  	_	Ancillary state register in rd (v9a)
>  	/	Ancillary state register in rs1 (v9a)
> -	(	entire floating point state register (%efsr).  */
> +	(	entire floating point state register (%efsr)
> +	=	2+8 bit PC relative immediate. (v9)  */
>  
>  #define OP2(x)		(((x) & 0x7) << 22)  /* Op2 field of format2 insns.  */
>  #define OP3(x)		(((x) & 0x3f) << 19) /* Op3 field of format3 insns.  */
> diff --git a/opcodes/sparc-dis.c b/opcodes/sparc-dis.c
> index b7f0cc2..7857e4c 100644
> --- a/opcodes/sparc-dis.c
> +++ b/opcodes/sparc-dis.c
> @@ -129,6 +129,7 @@ static char *v9a_asr_reg_names[] =
>  
>  /* These are for v9.  */
>  #define X_DISP16(i)  (((((i) >> 20) & 3) << 14) | (((i) >> 0) & 0x3fff))
> +#define X_DISP10(i)  (((((i) >> 19) & 3) << 8) | (((i) >> 5) & 0xff))
>  #define X_DISP19(i)  (((i) >> 0) & 0x7ffff)
>  #define X_MEMBAR(i)  ((i) & 0x7f)
>  
> @@ -743,6 +744,11 @@ print_insn_sparc (bfd_vma memaddr, disassemble_info *info)
>  		      break;
>  		    }
>  
> +		  case '=':
> +		    info->target = memaddr + SEX (X_DISP10 (insn), 10) * 4;
> +		    (*info->print_address_func) (info->target, info);
> +		    break;
> +
>  		  case 'k':
>  		    info->target = memaddr + SEX (X_DISP16 (insn), 16) * 4;
>  		    (*info->print_address_func) (info->target, info);



More information about the Binutils mailing list