IBM Z: Fix pcrel relocs for symA-symB expressions
authorAndreas Krebbel <krebbel@linux.ibm.com>
Mon, 3 Jul 2023 17:51:51 +0000 (19:51 +0200)
committerAndreas Krebbel <krebbel@linux.ibm.com>
Mon, 3 Jul 2023 17:52:02 +0000 (19:52 +0200)
The code in md_apply_fix which tries to deduce from the operand type
which reloc to apply currently does the wrong thing for absolute
relocs which have been re-written by fixup_segment as pc-relative to
implement a subtraction of a local and an external symbol.

In all these cases we wrongly emit an absolute reloc because we ignore
the fx_pcrel flag in md_apply_fix. However, only for the last one we
actually support a pc relative relocation of the proper size and can
implement it accordingly. For the other 3 we have to issue an error.

foo:
  cli 0(%r2),undef-foo
  la %r2,undef-foo(%r2)
  lay %r2,undef-foo(%r2)
  lhi %r2,undef-foo

gas/config/tc-s390.c
gas/testsuite/gas/s390/esa-reloc.d

index 955851946f9c1a0335f9bd548ffc38d816fc881b..765a9a2e6bda8c3a7219b9d6eff29a432a9674aa 100644 (file)
@@ -2291,25 +2291,25 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
         We are only prepared to turn a few of the operands into
         relocs.  */
       fixP->fx_offset = value;
-      if (operand->bits == 12 && operand->shift == 20)
+      if (operand->bits == 12 && operand->shift == 20 && !fixP->fx_pcrel)
        {
          fixP->fx_size = 2;
          fixP->fx_where += 2;
          fixP->fx_r_type = BFD_RELOC_390_12;
        }
-      else if (operand->bits == 12 && operand->shift == 36)
+      else if (operand->bits == 12 && operand->shift == 36 && !fixP->fx_pcrel)
        {
          fixP->fx_size = 2;
          fixP->fx_where += 4;
          fixP->fx_r_type = BFD_RELOC_390_12;
        }
-      else if (operand->bits == 20 && operand->shift == 20)
+      else if (operand->bits == 20 && operand->shift == 20 && !fixP->fx_pcrel)
        {
          fixP->fx_size = 4;
          fixP->fx_where += 2;
          fixP->fx_r_type = BFD_RELOC_390_20;
        }
-      else if (operand->bits == 8 && operand->shift == 8)
+      else if (operand->bits == 8 && operand->shift == 8 && !fixP->fx_pcrel)
        {
          fixP->fx_size = 1;
          fixP->fx_where += 1;
@@ -2334,6 +2334,12 @@ md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
              fixP->fx_offset += 2;
              fixP->fx_pcrel_adjust = 2;
            }
+         else if (fixP->fx_pcrel)
+           {
+             fixP->fx_r_type = BFD_RELOC_16_PCREL;
+             fixP->fx_offset += 2;
+             fixP->fx_pcrel_adjust = 2;
+           }
          else
            fixP->fx_r_type = BFD_RELOC_16;
        }
index c9da92870d511096609843b683ef470da614ea58..0b13cb626a6e9322f8003ec20a437fc3723b4133 100644 (file)
@@ -23,7 +23,7 @@ Disassembly of section .text:
   22:  a7 08 00 00 [   ]*lhi   %r0,0
 [      ]*24: R_390_GOT16       test_R_390_GOT16
   26:  a7 08 00 00 [   ]*lhi   %r0,0
-[      ]*28: R_390_16  test_R_390_PC16\+0x26
+[      ]*28: R_390_PC16        test_R_390_PC16\+0x28
   2a:  a7 e5 00 00 [   ]*bras  %r14,2a <foo\+0x2a>
 [      ]*2c: R_390_PC16DBL     test_R_390_PC16DBL\+0x2
   2e:  a7 e5 00 00 [   ]*bras  %r14,2e <foo\+0x2e>