Blame SOURCES/gdb-rhbz1320945-power9-03of38.patch

2c2fa1
commit b80eed39e2e813c37cffcb873dc4fdd03381383c
2c2fa1
Author: Alan Modra <amodra@gmail.com>
2c2fa1
Date:   Fri Mar 7 10:14:30 2014 +1030
2c2fa1
2c2fa1
    Better overflow checking for powerpc64 relocations
2c2fa1
    
2c2fa1
    R_PPC64_ADDR16 is used in three contexts:
2c2fa1
    - .short data relocation
2c2fa1
    - 16-bit signed insn fields, eg. addi
2c2fa1
    - 16-bit unsigned insn fields, eg. ori
2c2fa1
    In the first case we want to allow both signed and unsigned 16-bit
2c2fa1
    values, the latter two ought to error if the field exceeds the range
2c2fa1
    of values allowed for 16-bit signed and unsigned integers
2c2fa1
    respectively.  These conflicting requirements meant that ld had to
2c2fa1
    choose the least restrictive overflow checks, and thus it is possible
2c2fa1
    to construct testcases where an addi field overflows but is not
2c2fa1
    reported by ld.  Many relocations dealing with 16-bit insn fields have
2c2fa1
    this problem.  What's more, some relocations that are only ever used
2c2fa1
    for signed fields of instructions woodenly copied the lax overflow
2c2fa1
    checking of R_PPC64_ADDR16.
2c2fa1
    
2c2fa1
    bfd/
2c2fa1
            * elf64-ppc.c (ppc64_elf_howto_raw): Use complain_overflow_signed
2c2fa1
            for R_PPC64_ADDR14, R_PPC64_ADDR14_BRTAKEN, R_PPC64_ADDR14_BRNTAKEN,
2c2fa1
            R_PPC64_SECTOFF, R_PPC64_ADDR16_DS, R_PPC64_SECTOFF_DS,
2c2fa1
            R_PPC64_REL16 entries.  Use complain_overflow_dont for R_PPC64_TOC.
2c2fa1
            (ppc64_elf_relocate_section): Modify overflow test for 16-bit
2c2fa1
            fields in instructions to signed/unsigned according to whether
2c2fa1
            the field takes a signed or unsigned value.
2c2fa1
    gold/
2c2fa1
            * powerpc.cc (Powerpc_relocate_functions::Overflow_check): Add
2c2fa1
            CHECK_UNSIGNED, CHECK_LOW_INSN, CHECK_HIGH_INSN.
2c2fa1
            (Powerpc_relocate_functions::has_overflow_unsigned): New function.
2c2fa1
            (Powerpc_relocate_functions::has_overflow_bitfield,
2c2fa1
            overflowed): Use the above.
2c2fa1
            (Target_powerpc::Relocate::relocate): Correct overflow checking
2c2fa1
            for a number of relocations.  Modify overflow test for 16-bit
2c2fa1
            fields in instructions to signed/unsigned according to whether
2c2fa1
            the field takes a signed or unsigned value.
2c2fa1
2c2fa1
### a/bfd/ChangeLog
2c2fa1
### b/bfd/ChangeLog
2c2fa1
## -1,3 +1,13 @@
2c2fa1
+2014-03-08  Alan Modra  <amodra@gmail.com>
2c2fa1
+
2c2fa1
+	* elf64-ppc.c (ppc64_elf_howto_raw): Use complain_overflow_signed
2c2fa1
+	for R_PPC64_ADDR14, R_PPC64_ADDR14_BRTAKEN, R_PPC64_ADDR14_BRNTAKEN,
2c2fa1
+	R_PPC64_SECTOFF, R_PPC64_ADDR16_DS, R_PPC64_SECTOFF_DS,
2c2fa1
+	R_PPC64_REL16 entries.  Use complain_overflow_dont for R_PPC64_TOC.
2c2fa1
+	(ppc64_elf_relocate_section): Modify overflow test for 16-bit
2c2fa1
+	fields in instructions to signed/unsigned according to whether
2c2fa1
+	the field takes a signed or unsigned value.
2c2fa1
+
2c2fa1
 2014-03-07  Pedro Alves  <palves@redhat.com>
2c2fa1
 
2c2fa1
 	* rs6000-core.c (rs6000coff_core_p): Cast pointers to bfd_vma
2c2fa1
--- a/bfd/elf64-ppc.c
2c2fa1
+++ b/bfd/elf64-ppc.c
2c2fa1
@@ -357,7 +357,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_branch_reloc, /* special_function */
2c2fa1
 	 "R_PPC64_ADDR14",	/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -374,7 +374,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_brtaken_reloc, /* special_function */
2c2fa1
 	 "R_PPC64_ADDR14_BRTAKEN",/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -391,7 +391,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_brtaken_reloc, /* special_function */
2c2fa1
 	 "R_PPC64_ADDR14_BRNTAKEN",/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -632,7 +632,6 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 32,			/* bitsize */
2c2fa1
 	 TRUE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 /* FIXME: Verify.  Was complain_overflow_bitfield.  */
2c2fa1
 	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 bfd_elf_generic_reloc,	/* special_function */
2c2fa1
 	 "R_PPC64_REL32",	/* name */
2c2fa1
@@ -727,7 +726,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_sectoff_reloc, /* special_function */
2c2fa1
 	 "R_PPC64_SECTOFF",	/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -1015,7 +1014,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 64,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_dont, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_toc64_reloc,	/* special_function */
2c2fa1
 	 "R_PPC64_TOC",		/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -1103,7 +1102,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 bfd_elf_generic_reloc,	/* special_function */
2c2fa1
 	 "R_PPC64_ADDR16_DS",	/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -1178,7 +1177,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 FALSE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 ppc64_elf_sectoff_reloc, /* special_function */
2c2fa1
 	 "R_PPC64_SECTOFF_DS",	/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -1950,7 +1949,7 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
2c2fa1
 	 16,			/* bitsize */
2c2fa1
 	 TRUE,			/* pc_relative */
2c2fa1
 	 0,			/* bitpos */
2c2fa1
-	 complain_overflow_bitfield, /* complain_on_overflow */
2c2fa1
+	 complain_overflow_signed, /* complain_on_overflow */
2c2fa1
 	 bfd_elf_generic_reloc,	/* special_function */
2c2fa1
 	 "R_PPC64_REL16",	/* name */
2c2fa1
 	 FALSE,			/* partial_inplace */
2c2fa1
@@ -12943,6 +12942,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
2c2fa1
       bfd_vma max_br_offset;
2c2fa1
       bfd_vma from;
2c2fa1
       const Elf_Internal_Rela orig_rel = *rel;
2c2fa1
+      reloc_howto_type *howto;
2c2fa1
+      struct reloc_howto_struct alt_howto;
2c2fa1
 
2c2fa1
       r_type = ELF64_R_TYPE (rel->r_info);
2c2fa1
       r_symndx = ELF64_R_SYM (rel->r_info);
2c2fa1
@@ -14507,6 +14508,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
2c2fa1
 	}
2c2fa1
 
2c2fa1
       /* Do any further special processing.  */
2c2fa1
+      howto = ppc64_elf_howto_table[(int) r_type];
2c2fa1
       switch (r_type)
2c2fa1
 	{
2c2fa1
 	default:
2c2fa1
@@ -14581,7 +14583,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
2c2fa1
 	      info->callbacks->einfo
2c2fa1
 		(_("%P: %H: error: %s not a multiple of %u\n"),
2c2fa1
 		 input_bfd, input_section, rel->r_offset,
2c2fa1
-		 ppc64_elf_howto_table[r_type]->name,
2c2fa1
+		 howto->name,
2c2fa1
 		 mask + 1);
2c2fa1
 	      bfd_set_error (bfd_error_bad_value);
2c2fa1
 	      ret = FALSE;
2c2fa1
@@ -14602,23 +14604,45 @@ ppc64_elf_relocate_section (bfd *output_bfd,
2c2fa1
 	  info->callbacks->einfo
2c2fa1
 	    (_("%P: %H: unresolvable %s against `%T'\n"),
2c2fa1
 	     input_bfd, input_section, rel->r_offset,
2c2fa1
-	     ppc64_elf_howto_table[(int) r_type]->name,
2c2fa1
+	     howto->name,
2c2fa1
 	     h->elf.root.root.string);
2c2fa1
 	  ret = FALSE;
2c2fa1
 	}
2c2fa1
 
2c2fa1
-      r = _bfd_final_link_relocate (ppc64_elf_howto_table[(int) r_type],
2c2fa1
-				    input_bfd,
2c2fa1
-				    input_section,
2c2fa1
-				    contents,
2c2fa1
-				    rel->r_offset,
2c2fa1
-				    relocation,
2c2fa1
-				    addend);
2c2fa1
+      /* 16-bit fields in insns mostly have signed values, but a
2c2fa1
+	 few insns have 16-bit unsigned values.  Really, we should
2c2fa1
+	 have different reloc types.  */
2c2fa1
+      if (howto->complain_on_overflow != complain_overflow_dont
2c2fa1
+	  && howto->dst_mask == 0xffff
2c2fa1
+	  && (input_section->flags & SEC_CODE) != 0)
2c2fa1
+	{
2c2fa1
+	  enum complain_overflow complain = complain_overflow_signed;
2c2fa1
+
2c2fa1
+	  insn = bfd_get_32 (input_bfd, contents + (rel->r_offset & ~3));
2c2fa1
+	  if (howto->rightshift == 0
2c2fa1
+	      ? ((insn & (0x3f << 26)) == 28u << 26 /* andi */
2c2fa1
+		 || (insn & (0x3f << 26)) == 24u << 26 /* ori */
2c2fa1
+		 || (insn & (0x3f << 26)) == 26u << 26 /* xori */
2c2fa1
+		 || (insn & (0x3f << 26)) == 10u << 26 /* cmpli */)
2c2fa1
+	      : ((insn & (0x3f << 26)) == 29u << 26 /* andis */
2c2fa1
+		 || (insn & (0x3f << 26)) == 25u << 26 /* oris */
2c2fa1
+		 || (insn & (0x3f << 26)) == 27u << 26 /* xoris */))
2c2fa1
+	    complain = complain_overflow_unsigned;
2c2fa1
+	  if (howto->complain_on_overflow != complain)
2c2fa1
+	    {
2c2fa1
+	      alt_howto = *howto;
2c2fa1
+	      alt_howto.complain_on_overflow = complain;
2c2fa1
+	      howto = &alt_howto;
2c2fa1
+	    }
2c2fa1
+	}
2c2fa1
+
2c2fa1
+      r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents,
2c2fa1
+				    rel->r_offset, relocation, addend);
2c2fa1
 
2c2fa1
       if (r != bfd_reloc_ok)
2c2fa1
 	{
2c2fa1
 	  char *more_info = NULL;
2c2fa1
-	  const char *reloc_name = ppc64_elf_howto_table[r_type]->name;
2c2fa1
+	  const char *reloc_name = howto->name;
2c2fa1
 
2c2fa1
 	  if (reloc_dest != DEST_NORMAL)
2c2fa1
 	    {
2c2fa1
@@ -14638,7 +14662,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
2c2fa1
 		continue;
2c2fa1
 	      if (h != NULL
2c2fa1
 		  && h->elf.root.type == bfd_link_hash_undefweak
2c2fa1
-		  && ppc64_elf_howto_table[r_type]->pc_relative)
2c2fa1
+		  && howto->pc_relative)
2c2fa1
 		{
2c2fa1
 		  /* Assume this is a call protected by other code that
2c2fa1
 		     detects the symbol is undefined.  If this is the case,