[PATCH 3/5] x86: widen @got{,pcrel} support to PUSH and APX IMUL

H.J. Lu hjl.tools@gmail.com
Mon Feb 3 22:40:17 GMT 2025


On Mon, Feb 3, 2025 at 7:41 PM Jan Beulich <jbeulich@suse.com> wrote:
>
> With us doing the transformation to an immediate operand for MOV and
> various ALU insns, there's little reason to then not support the same
> conversion for the other two insns which have respective immediate
> operand forms. Unfortunately for IMUL (due to the 0F opcode prefix)
> there's no suitable relocation, so the pre-APX forms cannot be marked
> for relaxation in the assembler.
> ---
> TBD: Is REX2 really permitted with PUSH <imm>?
>
> --- a/bfd/elf32-i386.c
> +++ b/bfd/elf32-i386.c
> @@ -1209,6 +1209,10 @@ elf_i386_tls_transition (struct bfd_link
>     to
>     test $foo, %reg1
>     and convert
> +   push foo@GOT[(%reg)]
> +   to
> +   push $foo
> +   and convert
>     binop foo@GOT[(%reg1)], %reg2
>     to
>     binop $foo, %reg2
> @@ -1233,7 +1237,7 @@ elf_i386_convert_load_reloc (bfd *abfd,
>    unsigned int addend;
>    unsigned int nop;
>    bfd_vma nop_offset;
> -  bool is_pic;
> +  bool is_pic, is_branch = false;
>    bool to_reloc_32;
>    bool abs_symbol;
>    unsigned int r_type;
> @@ -1301,6 +1305,23 @@ elf_i386_convert_load_reloc (bfd *abfd,
>
>    opcode = bfd_get_8 (abfd, contents + roff - 2);
>
> +  if (opcode == 0xff)
> +    {
> +      switch (modrm & 0x38)
> +       {
> +       case 0x10: /* CALL */
> +       case 0x20: /* JMP */
> +         is_branch = true;
> +         break;
> +
> +       case 0x30: /* PUSH */
> +         break;
> +
> +       default:
> +         return true;
> +       }
> +    }
> +
>    /* Convert to R_386_32 if PIC is false or there is no base
>       register.  */
>    to_reloc_32 = !is_pic || baseless;
> @@ -1311,7 +1332,7 @@ elf_i386_convert_load_reloc (bfd *abfd,
>       reloc.  */
>    if (h == NULL)
>      {
> -      if (opcode == 0x0ff)
> +      if (is_branch)
>         /* Convert "call/jmp *foo@GOT[(%reg)]".  */
>         goto convert_branch;
>        else
> @@ -1327,7 +1348,7 @@ elf_i386_convert_load_reloc (bfd *abfd,
>        && !eh->linker_def
>        && local_ref)
>      {
> -      if (opcode == 0xff)
> +      if (is_branch)
>         {
>           /* No direct branch to 0 for PIC.  */
>           if (is_pic)
> @@ -1343,7 +1364,7 @@ elf_i386_convert_load_reloc (bfd *abfd,
>         }
>      }
>
> -  if (opcode == 0xff)
> +  if (is_branch)
>      {
>        /* We have "call/jmp *foo@GOT[(%reg)]".  */
>        if ((h->root.type == bfd_link_hash_defined
> @@ -1399,7 +1420,8 @@ elf_i386_convert_load_reloc (bfd *abfd,
>    else
>      {
>        /* We have "mov foo@GOT[(%re1g)], %reg2",
> -        "test %reg1, foo@GOT(%reg2)" and
> +        "test %reg1, foo@GOT(%reg2)",
> +        "push foo@GOT[(%reg)]", or
>          "binop foo@GOT[(%reg1)], %reg2".
>
>          Avoid optimizing _DYNAMIC since ld.so may use its
> @@ -1460,6 +1482,13 @@ elf_i386_convert_load_reloc (bfd *abfd,
>                   modrm = 0xc0 | ((modrm & 0x38) >> 3) | (opcode & 0x38);
>                   opcode = 0x81;
>                 }
> +             else if (opcode == 0xff)
> +               {
> +                 /* Convert "push foo@GOT(%reg)" to
> +                    "push $foo".  */
> +                 modrm = 0x68; /* Really the opcode.  */
> +                 opcode = 0x26; /* Really a meaningless %es: prefix.  */
> +               }
>               else
>                 return true;
>
> --- a/bfd/elf64-x86-64.c
> +++ b/bfd/elf64-x86-64.c
> @@ -1739,13 +1739,16 @@ elf_x86_64_need_pic (struct bfd_link_inf
>  }
>
>  /* Move the R bits to the B bits in EVEX payload byte 1.  */
> -static unsigned int evex_move_r_to_b (unsigned int byte1)
> +static unsigned int evex_move_r_to_b (unsigned int byte1, bool copy)
>  {
>    byte1 = (byte1 & ~(1 << 5)) | ((byte1 & (1 << 7)) >> 2); /* R3 -> B3 */
>    byte1 = (byte1 & ~(1 << 3)) | ((~byte1 & (1 << 4)) >> 1); /* R4 -> B4 */
>
>    /* Set both R bits, as they're inverted.  */
> -  return byte1 | (1 << 4) | (1 << 7);
> +  if (!copy)
> +    byte1 |= (1 << 4) | (1 << 7);
> +
> +  return byte1;
>  }
>
>  /* With the local symbol, foo, we convert
> @@ -1762,10 +1765,14 @@ static unsigned int evex_move_r_to_b (un
>     to
>     test $foo, %reg
>     and convert
> +   push foo@GOTPCREL(%rip)
> +   to
> +   push $foo
> +   and convert
>     binop foo@GOTPCREL(%rip), %reg
>     to
>     binop $foo, %reg
> -   where binop is one of adc, add, and, cmp, or, sbb, sub, xor
> +   where binop is one of adc, add, and, cmp, imul, or, sbb, sub, xor
>     instructions.  */
>
>  static bool
> @@ -1781,6 +1788,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>    bool is_pic;
>    bool no_overflow;
>    bool relocx;
> +  bool is_branch = false;
>    bool to_reloc_pc32;
>    bool abs_symbol;
>    bool local_ref;
> @@ -1873,6 +1881,23 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>    r_symndx = htab->r_sym (irel->r_info);
>
>    opcode = bfd_get_8 (abfd, contents + roff - 2);
> +  modrm = bfd_get_8 (abfd, contents + roff - 1);
> +  if (opcode == 0xff)
> +    {
> +      switch (modrm & 0x38)
> +       {
> +       case 0x10: /* CALL */
> +       case 0x20: /* JMP */
> +         is_branch = true;
> +         break;
> +
> +       case 0x30: /* PUSH */
> +         break;
> +
> +       default:
> +         return true;
> +       }
> +    }
>
>    /* Convert mov to lea since it has been done for a while.  */
>    if (opcode != 0x8b)
> @@ -1890,7 +1915,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>       3. no_overflow is true.
>       4. PIC.
>       */
> -  to_reloc_pc32 = (opcode == 0xff
> +  to_reloc_pc32 = (is_branch
>                    || !relocx
>                    || no_overflow
>                    || is_pic);
> @@ -1942,7 +1967,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>               && !eh->linker_def
>               && local_ref))
>         {
> -         if (opcode == 0xff)
> +         if (is_branch)
>             {
>               /* Skip for branch instructions since R_X86_64_PC32
>                  may overflow.  */
> @@ -2009,7 +2034,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>      return true;
>
>   convert:
> -  if (opcode == 0xff)
> +  if (is_branch)
>      {
>        /* We have "call/jmp *foo@GOTPCREL(%rip)".  */
>        unsigned int nop;
> @@ -2018,7 +2043,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>
>        /* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to
>          R_X86_64_PC32.  */
> -      modrm = bfd_get_8 (abfd, contents + roff - 1);
>        if (modrm == 0x25)
>         {
>           /* Convert to "jmp foo nop".  */
> @@ -2064,11 +2088,12 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>      }
>    else if (r_type == R_X86_64_CODE_6_GOTPCRELX && opcode != 0x8b)
>      {
> +      bool move_v_r = false;
> +
>        /* R_X86_64_PC32 isn't supported.  */
>        if (to_reloc_pc32)
>         return true;
>
> -      modrm = bfd_get_8 (abfd, contents + roff - 1);
>        if (opcode == 0x85)
>         {
>           /* Convert "ctest<cc> %reg, foo@GOTPCREL(%rip)" to
> @@ -2094,6 +2119,23 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>           modrm = 0xc0 | ((modrm & 0x38) >> 3) | (opcode & 0x38);
>           opcode = 0x81;
>         }
> +      else if (opcode == 0xaf)
> +       {
> +         if (!(evex[2] & 0x10))
> +           {
> +             /* Convert "imul foo@GOTPCREL(%rip), %reg" to
> +                "imul $foo, %reg, %reg".  */
> +             modrm = 0xc0 | ((modrm & 0x38) >> 3) | (modrm & 0x38);
> +           }
> +         else
> +           {
> +             /* Convert "imul foo@GOTPCREL(%rip), %reg1, %reg2" to
> +                "imul $foo, %reg1, %reg2".  */
> +             modrm = 0xc0 | ((modrm & 0x38) >> 3) | (~evex[1] & 0x38);
> +             move_v_r = true;
> +           }
> +         opcode = 0x69;
> +       }
>        else
>         return true;
>
> @@ -2119,7 +2161,23 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>        bfd_put_8 (abfd, opcode, contents + roff - 2);
>        bfd_put_8 (abfd, modrm, contents + roff - 1);
>
> -      evex[0] = evex_move_r_to_b (evex[0]);
> +      evex[0] = evex_move_r_to_b (evex[0], opcode == 0x69 && !move_v_r);
> +      if (move_v_r)
> +       {
> +         /* Move the top two V bits to the R bits in EVEX payload byte 1.
> +            Note that evex_move_r_to_b() set both R bits.  */
> +         if (!(evex[1] & (1 << 6)))
> +           evex[0] &= ~(1 << 7); /* V3 -> R3 */
> +         if (!(evex[2] & (1 << 3)))
> +           evex[0] &= ~(1 << 4); /* V4 -> R4 */
> +         /* Set all V bits, as they're inverted.  */
> +         evex[1] |= 0xf << 3;
> +         evex[2] |= 1 << 3;
> +         /* Clear the ND (ZU) bit (it ought to be ignored anyway).  */
> +         evex[2] &= ~(1 << 4);
> +         bfd_put_8 (abfd, evex[2], contents + roff - 3);
> +         bfd_put_8 (abfd, evex[1], contents + roff - 4);
> +       }
>        bfd_put_8 (abfd, evex[0], contents + roff - 5);
>
>        /* No addend for R_X86_64_32/R_X86_64_32S relocations.  */
> @@ -2162,7 +2220,10 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>         {
>           if (bfd_get_8 (abfd, contents + roff - 4) == 0xd5)
>             {
> -             rex2 = bfd_get_8 (abfd, contents + roff - 3);
> +             /* Make sure even an all-zero payload leaves a non-zero value
> +                in the variable.  */
> +             rex2 = bfd_get_8 (abfd, contents + roff - 3) | 0x100;
> +             rex2_mask |= 0x100;
>               rex_w = (rex2 & REX_W) != 0;
>             }
>           else if (bfd_get_8 (abfd, contents + roff - 4) == 0x0f)
> @@ -2195,7 +2256,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>               /* Convert "mov foo@GOTPCREL(%rip), %reg" to
>                  "mov $foo, %reg".  */
>               opcode = 0xc7;
> -             modrm = bfd_get_8 (abfd, contents + roff - 1);
>               modrm = 0xc0 | (modrm & 0x38) >> 3;
>               if (rex_w && ABI_64_P (link_info->output_bfd))
>                 {
> @@ -2222,7 +2282,6 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>           if (to_reloc_pc32)
>             return true;
>
> -         modrm = bfd_get_8 (abfd, contents + roff - 1);
>           if (opcode == 0x85)
>             {
>               /* Convert "test %reg, foo@GOTPCREL(%rip)" to
> @@ -2237,6 +2296,39 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>               modrm = 0xc0 | ((modrm & 0x38) >> 3) | (opcode & 0x38);
>               opcode = 0x81;
>             }
> +         else if (opcode == 0xaf && (rex2 & (REX2_M << 4)))
> +           {
> +             /* Convert "imul foo@GOTPCREL(%rip), %reg" to
> +                "imul $foo, %reg, %reg".  */
> +             modrm = 0xc0 | ((modrm & 0x38) >> 3) | (modrm & 0x38);
> +             rex_mask = 0;
> +             rex2_mask = REX2_M << 4;
> +             opcode = 0x69;
> +           }
> +         else if (opcode == 0xff && !(rex2 & (REX2_M << 4)))
> +           {
> +             /* Convert "push foo@GOTPCREL(%rip)" to
> +                "push $foo".  */
> +             bfd_put_8 (abfd, 0x68, contents + roff - 1);
> +             if (rex)
> +               {
> +                 bfd_put_8 (abfd, 0x26, contents + roff - 3);
> +                 bfd_put_8 (abfd, rex, contents + roff - 2);
> +               }
> +             else if (rex2)
> +               {
> +                 bfd_put_8 (abfd, 0x26, contents + roff - 4);
> +                 bfd_put_8 (abfd, 0xd5, contents + roff - 3);
> +                 bfd_put_8 (abfd, rex2, contents + roff - 2);
> +               }
> +             else
> +               bfd_put_8 (abfd, 0x26, contents + roff - 2);
> +
> +             r_type = R_X86_64_32S;
> +             /* No addend for R_X86_64_32S relocations.  */
> +             irel->r_addend = 0;
> +             goto finish;
> +           }
>           else
>             return true;
>
> @@ -2297,6 +2389,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd
>         }
>      }
>
> + finish:
>    *r_type_p = r_type;
>    irel->r_info = htab->r_info (r_symndx,
>                                r_type | R_X86_64_converted_reloc_bit);
> @@ -4378,7 +4471,7 @@ elf_x86_64_relocate_section (bfd *output
>                       continue;
>                     }
>
> -                 byte1 = evex_move_r_to_b (byte1);
> +                 byte1 = evex_move_r_to_b (byte1, false);
>                   bfd_put_8 (output_bfd, byte1, contents + roff - 5);
>                   bfd_put_8 (output_bfd, 0x81, contents + roff - 2);
>                   bfd_put_8 (output_bfd, 0xc0 | reg, contents + roff - 1);
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -12928,9 +12928,9 @@ output_disp (fragS *insn_start_frag, off
>               else if (object_64bit)
>                 continue;
>
> -             /* Check for "call/jmp *mem", "mov mem, %reg", "movrs mem, %reg",
> -                "test %reg, mem" and "binop mem, %reg" where binop
> -                is one of adc, add, and, cmp, or, sbb, sub, xor
> +             /* Check for "call/jmp *mem", "push mem", "mov mem, %reg",
> +                "movrs mem, %reg", "test %reg, mem" and "binop mem, %reg" where
> +                binop is one of adc, add, and, cmp, or, sbb, sub, xor, or imul
>                  instructions without data prefix.  Always generate
>                  R_386_GOT32X for "sym*GOT" operand in 32-bit mode.  */
>               unsigned int space = dot_insn () ? i.insn_opcode_space
> @@ -12940,7 +12940,7 @@ output_disp (fragS *insn_start_frag, off
>                       || (i.rm.mode == 0 && i.rm.regmem == 5))
>                   && ((space == SPACE_BASE
>                        && i.tm.base_opcode == 0xff
> -                      && (i.rm.reg == 2 || i.rm.reg == 4))
> +                      && (i.rm.reg == 2 || i.rm.reg == 4 || i.rm.reg == 6))
>                       || ((space == SPACE_BASE
>                            || space == SPACE_0F38
>                            || space == SPACE_MAP4)
> @@ -12949,7 +12949,13 @@ output_disp (fragS *insn_start_frag, off
>                            || space == SPACE_MAP4)
>                           && (i.tm.base_opcode == 0x85
>                               || (i.tm.base_opcode
> -                                 | (i.operands > 2 ? 0x3a : 0x38)) == 0x3b))))
> +                                 | (i.operands > 2 ? 0x3a : 0x38)) == 0x3b))
> +                     || (((space == SPACE_0F
> +                           /* Because of the 0F prefix, no suitable relocation
> +                              exists for this unless it's REX2-encoded.  */
> +                           && is_apx_rex2_encoding ())
> +                          || space == SPACE_MAP4)
> +                         && i.tm.base_opcode == 0xaf)))
>                 {
>                   if (object_64bit)
>                     {
> --- a/ld/testsuite/ld-i386/i386.exp
> +++ b/ld/testsuite/ld-i386/i386.exp
> @@ -373,6 +373,8 @@ run_dump_test "load5a"
>  run_dump_test "load5b"
>  run_dump_test "load6"
>  run_dump_test "load7"
> +run_dump_test "load8a"
> +run_dump_test "load8b"
>  run_dump_test "pr19175"
>  run_dump_test "pr19615"
>  run_dump_test "pr19636-1a"
> --- /dev/null
> +++ b/ld/testsuite/ld-i386/load8.s
> @@ -0,0 +1,20 @@
> +       .data
> +       .type   bar, @object
> +bar:
> +       .byte   1
> +       .size   bar, .-bar
> +       .globl  foo
> +       .type   foo, @object
> +foo:
> +       .byte   1
> +       .size   foo, .-foo
> +       .text
> +       .globl  _start
> +       .type   _start, @function
> +_start:
> +       push    bar@GOT(%ecx)
> +       push    foo@GOT(%edx)
> +       .ifndef PIC
> +       push    foo@GOT
> +       .endif
> +       .size   _start, .-_start
> --- /dev/null
> +++ b/ld/testsuite/ld-i386/load8a.d
> @@ -0,0 +1,14 @@
> +#source: load8.s
> +#as: --32 -mrelax-relocations=yes
> +#ld: -melf_i386 -z noseparate-code
> +#objdump: -dw
> +
> +.*: +file format .*
> +
> +Disassembly of section .text:
> +
> +0+8048074 <_start>:
> +[      ]*[a-f0-9]+:    26 68 86 90 04 08       es push \$0x8049086
> +[      ]*[a-f0-9]+:    26 68 87 90 04 08       es push \$0x8049087
> +[      ]*[a-f0-9]+:    26 68 87 90 04 08       es push \$0x8049087

Please avoid adding the es prefix.  It may not be nop in the future.

> +#pass
> --- /dev/null
> +++ b/ld/testsuite/ld-i386/load8b.d
> @@ -0,0 +1,13 @@
> +#source: load8.s
> +#as: --32 -mshared -mrelax-relocations=yes --defsym PIC=1
> +#ld: -melf_i386 -shared -z noseparate-code
> +#objdump: -dw
> +
> +.*: +file format .*
> +
> +Disassembly of section .text:
> +
> +0+[0-9a-f]+ <_start>:
> +[      ]*[0-9a-f]+:    ff b1 f8 ff ff ff       push   -0x8\(%ecx\)
> +[      ]*[0-9a-f]+:    ff b2 fc ff ff ff       push   -0x4\(%edx\)
> +#pass
> --- a/ld/testsuite/ld-x86-64/apx-load1.s
> +++ b/ld/testsuite/ld-x86-64/apx-load1.s
> @@ -118,5 +118,11 @@ _start:
>         sub     %rbp, bar@GOTPCREL(%rip), %r21
>         xor     %rsi, bar@GOTPCREL(%rip), %r22
>
> +       imul    bar@GOTPCREL(%rip), %r17
> +       {nf} imul bar@GOTPCREL(%rip), %r17
> +       imul    bar@GOTPCREL(%rip), %r17, %rdx
> +       imul    bar@GOTPCREL(%rip), %rcx, %r18
> +       {rex2} pushq bar@GOTPCREL(%rip)
> +
>         .size   _start, .-_start
>         .p2align 12, 0x90
> --- a/ld/testsuite/ld-x86-64/apx-load1a.d
> +++ b/ld/testsuite/ld-x86-64/apx-load1a.d
> @@ -115,4 +115,9 @@ Disassembly of section .text:
>   +[a-f0-9]+:   62 f4 dc 10 19 25 74 0c 20 00   sbb    %rsp,0x200c74\(%rip\),%r20        # 602000 <.*>
>   +[a-f0-9]+:   62 f4 d4 10 29 2d 6a 0c 20 00   sub    %rbp,0x200c6a\(%rip\),%r21        # 602000 <.*>
>   +[a-f0-9]+:   62 f4 cc 10 81 f6 20 20 60 00   xor    \$0x602020,%rsi,%r22
> + +[a-f0-9]+:   d5 58 69 c9 20 20 60 00         imul   \$0x602020,%r17,%r17
> + +[a-f0-9]+:   62 ec fc 0c 69 c9 20 20 60 00   \{nf\} imul \$0x602020,%r17,%r17
> + +[a-f0-9]+:   62 fc fc 08 69 d1 20 20 60 00   imul   \$0x602020,%r17,%rdx
> + +[a-f0-9]+:   62 e4 fc 08 69 d1 20 20 60 00   imul   \$0x602020,%rcx,%r18
> + +[a-f0-9]+:   26 d5 00 68 20 20 60 00         es \{rex2 0x0\} push \$0x602020
>  #pass
> --- a/ld/testsuite/ld-x86-64/apx-load1c.d
> +++ b/ld/testsuite/ld-x86-64/apx-load1c.d
> @@ -108,4 +108,9 @@ Disassembly of section .text:
>   +[a-f0-9]+:   62 f4 dc 10 19 25 54 0d 20 00   sbb    %rsp,0x200d54\(%rip\),%r20        # 2020e0 <.*>
>   +[a-f0-9]+:   62 f4 d4 10 29 2d 4a 0d 20 00   sub    %rbp,0x200d4a\(%rip\),%r21        # 2020e0 <.*>
>   +[a-f0-9]+:   62 f4 cc 10 31 35 40 0d 20 00   xor    %rsi,0x200d40\(%rip\),%r22        # 2020e0 <.*>
> + +[a-f0-9]+:   d5 c8 af 0d 38 0d 20 00         imul   0x200d38\(%rip\),%r17        # 2020e0 <.*>
> + +[a-f0-9]+:   62 e4 fc 0c af 0d 2e 0d 20 00   \{nf\} imul 0x200d2e\(%rip\),%r17        # 2020e0 <.*>
> + +[a-f0-9]+:   62 e4 ec 18 af 0d 24 0d 20 00   imul   0x200d24\(%rip\),%r17,%rdx        # 2020e0 <.*>
> + +[a-f0-9]+:   62 f4 ec 10 af 0d 1a 0d 20 00   imul   0x200d1a\(%rip\),%rcx,%r18        # 2020e0 <.*>
> + +[a-f0-9]+:   d5 00 ff 35 12 0d 20 00         \{rex2 0x0\} push 0x200d12\(%rip\)        # 2020e0 <.*>
>  #pass
> --- a/ld/testsuite/ld-x86-64/apx-load1d.d
> +++ b/ld/testsuite/ld-x86-64/apx-load1d.d
> @@ -108,4 +108,9 @@ Disassembly of section .text:
>   +[a-f0-9]+:   62 f4 dc 10 19 25 e4 0c 20 00   sbb    %rsp,0x200ce4\(%rip\),%r20        # 202070 <.*>
>   +[a-f0-9]+:   62 f4 d4 10 29 2d da 0c 20 00   sub    %rbp,0x200cda\(%rip\),%r21        # 202070 <.*>
>   +[a-f0-9]+:   62 f4 cc 10 31 35 d0 0c 20 00   xor    %rsi,0x200cd0\(%rip\),%r22        # 202070 <.*>
> + +[a-f0-9]+:   d5 c8 af 0d c8 0c 20 00         imul   0x200cc8\(%rip\),%r17        # 202070 <.*>
> + +[a-f0-9]+:   62 e4 fc 0c af 0d be 0c 20 00   \{nf\} imul 0x200cbe\(%rip\),%r17        # 202070 <.*>
> + +[a-f0-9]+:   62 e4 ec 18 af 0d b4 0c 20 00   imul   0x200cb4\(%rip\),%r17,%rdx        # 202070 <.*>
> + +[a-f0-9]+:   62 f4 ec 10 af 0d aa 0c 20 00   imul   0x200caa\(%rip\),%rcx,%r18        # 202070 <.*>
> + +[a-f0-9]+:   d5 00 ff 35 a2 0c 20 00         \{rex2 0x0\} push 0x200ca2\(%rip\)        # 202070 <.*>
>  #pass
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/load5.s
> @@ -0,0 +1,17 @@
> +       .data
> +       .type   bar, @object
> +bar:
> +       .byte   1
> +       .size   bar, .-bar
> +       .globl  foo
> +       .type   foo, @object
> +foo:
> +       .byte   1
> +       .size   foo, .-foo
> +       .text
> +       .globl  _start
> +       .type   _start, @function
> +_start:
> +             pushq     bar@GOTPCREL(%rip)
> +       {rex} pushq     foo@GOTPCREL(%rip)
> +       .size   _start, .-_start
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/load5a.d
> @@ -0,0 +1,15 @@
> +#source: load5.s
> +#as: --64 -mrelax-relocations=yes
> +#ld: -melf_x86_64
> +#objdump: -dw
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +#...
> +[a-f0-9]+ <_start>:
> +[      ]*[a-f0-9]+:    26 68 ([0-9a-f]{2} ){4} *       es push \$0x[a-f0-9]+
> +[      ]*[a-f0-9]+:    26 40 68 ([0-9a-f]{2} ){4} *    es rex push \$0x[a-f0-9]+
> +#pass
> --- /dev/null
> +++ b/ld/testsuite/ld-x86-64/load5b.d
> @@ -0,0 +1,15 @@
> +#source: load5.s
> +#as: --64 -mrelax-relocations=yes
> +#ld: -shared -melf_x86_64
> +#objdump: -dw
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +#...
> +[a-f0-9]+ <_start>:
> +[      ]*[a-f0-9]+:    ff 35 ([0-9a-f]{2} ){4} *       push +0x[a-f0-9]+\(%rip\)        # [a-f0-9]+ <.*>
> +[      ]*[a-f0-9]+:    40 ff 35 ([0-9a-f]{2} ){4} *    rex push 0x[a-f0-9]+\(%rip\)        # [a-f0-9]+ <.*>
> +#pass
> --- a/ld/testsuite/ld-x86-64/x86-64.exp
> +++ b/ld/testsuite/ld-x86-64/x86-64.exp
> @@ -654,6 +654,8 @@ run_dump_test "load2"
>  run_dump_test "load3a"
>  run_dump_test "load3b"
>  run_dump_test "load4"
> +run_dump_test "load5a"
> +run_dump_test "load5b"
>  run_dump_test "call1a"
>  run_dump_test "call1b"
>  run_dump_test "call1c"
>


-- 
H.J.


More information about the Binutils mailing list