PR24697, R_PPC_EMB_SDA21 relocation
authorAlan Modra <amodra@gmail.com>
Wed, 19 Jun 2019 04:25:59 +0000 (13:55 +0930)
committerAlan Modra <amodra@gmail.com>
Wed, 19 Jun 2019 04:31:19 +0000 (14:01 +0930)
PR 24697
* elf32-ppc.c (ppc_elf_relocate_section): Don't read insn for
R_PPC_EMB_RELSDA.  Mask low bit of R_PPC_EMB_SDA21 r_offset.

bfd/ChangeLog
bfd/elf32-ppc.c

index ea049b1d423c430c1295816fe134ce888ca1fe9f..f40f6ed63dc8fdcaec2d735344c45c194cb41e21 100644 (file)
@@ -1,3 +1,9 @@
+2019-06-19  Alan Modra  <amodra@gmail.com>
+
+       PR 24697
+       * elf32-ppc.c (ppc_elf_relocate_section): Don't read insn for
+       R_PPC_EMB_RELSDA.  Mask low bit of R_PPC_EMB_SDA21 r_offset.
+
 2019-06-19  Alan Modra  <amodra@gmail.com>
 
        * elf64-ppc.c (ppc64_elf_inline_plt): Correct st_other test for
index e73539afa2b1d17e92b52b2f3297d3b7f1a23ea2..df813d36cc5c5870fda44a0839f1e0710d34a7ce 100644 (file)
@@ -8654,6 +8654,19 @@ ppc_elf_relocate_section (bfd *output_bfd,
                addend -= SYM_VAL (sda);
              }
 
+           if (r_type == R_PPC_EMB_RELSDA)
+             break;
+
+           /* The PowerPC Embedded Application Binary Interface
+              version 1.0 insanely chose to specify R_PPC_EMB_SDA21
+              operating on a 24-bit field at r_offset.  GNU as and
+              GNU ld have always assumed R_PPC_EMB_SDA21 operates on
+              a 32-bit bit insn at r_offset.  Cope with object file
+              producers that possibly comply with the EABI in
+              generating an odd r_offset for big-endian objects.  */
+           if (r_type == R_PPC_EMB_SDA21)
+             rel->r_offset &= ~1;
+
            insn = bfd_get_32 (input_bfd, contents + rel->r_offset);
            if (reg == 0
                && (r_type == R_PPC_VLE_SDA21
@@ -8681,13 +8694,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
                  goto overflow;
                goto copy_reloc;
              }
-           else if (r_type == R_PPC_EMB_SDA21
-                    || r_type == R_PPC_VLE_SDA21
-                    || r_type == R_PPC_VLE_SDA21_LO)
-             {
-               /* Fill in register field.  */
-               insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
-             }
+           /* Fill in register field.  */
+           insn = (insn & ~RA_REGISTER_MASK) | (reg << RA_REGISTER_SHIFT);
            bfd_put_32 (input_bfd, insn, contents + rel->r_offset);
          }
          break;