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

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