[PATCH 7/8] x86: relax when/how @size can be used

H.J. Lu hjl.tools@gmail.com
Fri Apr 23 13:35:02 GMT 2021


On Fri, Apr 23, 2021 at 1:38 AM Jan Beulich <jbeulich@suse.com> wrote:
>
> Allow a few more expression forms when the entire expression can be
> resolved at assembly time. For this, i386_validate_fix() needs to
> arrange for all processing of the relocation to be deferred to
> tc_gen_reloc().
>
> gas/
> 2021-04-XX  Jan Beulich  <jbeulich@suse.com>
>
>         * config/tc-i386.c (i386_validate_fix): Change return type to
>         int. Short-circuit BFD_RELOC_SIZE* handling.
>         (tc_gen_reloc): New local variable sym. Extend logic when
>         processing BFD_RELOC_SIZE*.
>         * config/tc-i386.f (i386_validate_fix): Change return type to
>         int.
>         (TC_VALIDATE_FIX): Proceed to SKIP when i386_validate_fix()
>         returns zero.
>         * testsuite/gas/i386/size-5.s, testsuite/gas/i386/size-5a.d,
>         testsuite/gas/i386/size-5b.d: New.
>         * testsuite/gas/i386/i386.exp: Run new tests.
>
> ---
> Somewhat related, I think that @size would be useful to expose to no-ELF
> as well, just that its use would be limited to locally defined symbols.
> This might then mean that "x86: add IS_ELF to check whether to resolve
> @size reloc" would better be dropped / replaced.
>
> --- a/gas/config/tc-i386.c
> +++ b/gas/config/tc-i386.c
> @@ -14171,9 +14171,17 @@ i386_cons_align (int ignore ATTRIBUTE_UN
>      }
>  }
>
> -void
> +int
>  i386_validate_fix (fixS *fixp)
>  {
> +#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
> +  if (fixp->fx_r_type == BFD_RELOC_SIZE32
> +      || fixp->fx_r_type == BFD_RELOC_SIZE64)
> +    return IS_ELF && fixp->fx_addsy
> +          && (!S_IS_DEFINED (fixp->fx_addsy)
> +              || S_IS_EXTERNAL (fixp->fx_addsy));
> +#endif
> +
>    if (fixp->fx_subsy)
>      {
>        if (fixp->fx_subsy == GOT_symbol)
> @@ -14220,6 +14228,8 @@ i386_validate_fix (fixS *fixp)
>         }
>      }
>  #endif
> +
> +  return 1;
>  }
>
>  arelent *
> @@ -14231,18 +14241,38 @@ tc_gen_reloc (asection *section ATTRIBUT
>    switch (fixp->fx_r_type)
>      {
>  #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
> +      symbolS *sym;
> +
>      case BFD_RELOC_SIZE32:
>      case BFD_RELOC_SIZE64:
> -      if (IS_ELF
> -         && S_IS_DEFINED (fixp->fx_addsy)
> -         && !S_IS_EXTERNAL (fixp->fx_addsy))
> +      if (fixp->fx_addsy
> +         && !bfd_is_abs_section (S_GET_SEGMENT (fixp->fx_addsy))
> +         && (!fixp->fx_subsy
> +             || bfd_is_abs_section (S_GET_SEGMENT (fixp->fx_subsy))))
> +       sym = fixp->fx_addsy;
> +      else if (fixp->fx_subsy
> +              && !bfd_is_abs_section (S_GET_SEGMENT (fixp->fx_subsy))
> +              && (!fixp->fx_addsy
> +                  || bfd_is_abs_section (S_GET_SEGMENT (fixp->fx_addsy))))
> +       sym = fixp->fx_subsy;
> +      else
> +       sym = NULL;
> +      if (IS_ELF && sym && S_IS_DEFINED (sym) && !S_IS_EXTERNAL (sym))
>         {
>           /* Resolve size relocation against local symbol to size of
>              the symbol plus addend.  */
> -         valueT value = S_GET_SIZE (fixp->fx_addsy);
> +         valueT value = S_GET_SIZE (sym);
>
> -         if (symbol_get_bfdsym (fixp->fx_addsy)->flags & BSF_SECTION_SYM)
> -           value = bfd_section_size (S_GET_SEGMENT (fixp->fx_addsy));
> +         if (symbol_get_bfdsym (sym)->flags & BSF_SECTION_SYM)
> +           value = bfd_section_size (S_GET_SEGMENT (sym));
> +         if (sym == fixp->fx_subsy)
> +           {
> +             value = -value;
> +             if (fixp->fx_addsy)
> +               value += S_GET_VALUE (fixp->fx_addsy);
> +           }
> +         else if (fixp->fx_subsy)
> +           value -= S_GET_VALUE (fixp->fx_subsy);
>           value += fixp->fx_offset;
>           if (fixp->fx_r_type == BFD_RELOC_SIZE32
>               && object_64bit
> @@ -14254,6 +14284,12 @@ tc_gen_reloc (asection *section ATTRIBUT
>           md_apply_fix (fixp, (valueT *) &value, NULL);
>           return NULL;
>         }
> +      if (!fixp->fx_addsy || fixp->fx_subsy)
> +       {
> +         as_bad_where (fixp->fx_file, fixp->fx_line,
> +                       "unsupported expression involving @size");
> +         return NULL;
> +       }
>  #endif
>        /* Fall through.  */
>
> --- a/gas/config/tc-i386.h
> +++ b/gas/config/tc-i386.h
> @@ -143,8 +143,10 @@ extern int x86_address_bytes (void);
>
>  #define NO_RELOC BFD_RELOC_NONE
>
> -void i386_validate_fix (struct fix *);
> -#define TC_VALIDATE_FIX(FIX,SEGTYPE,SKIP) i386_validate_fix(FIX)
> +int i386_validate_fix (struct fix *);
> +#define TC_VALIDATE_FIX(FIX,SEGTYPE,SKIP) do { \
> +    if (!i386_validate_fix(FIX)) goto SKIP;      \
> +  } while (0)
>
>  #define tc_fix_adjustable(X)  tc_i386_fix_adjustable(X)
>  extern int tc_i386_fix_adjustable (struct fix *);
> --- a/gas/testsuite/gas/i386/i386.exp
> +++ b/gas/testsuite/gas/i386/i386.exp
> @@ -637,6 +637,8 @@ if [gas_32_check] then {
>         run_dump_test "size-2"
>         run_dump_test "size-3"
>         run_dump_test "size-4"
> +       run_dump_test "size-5a"
> +       run_dump_test "size-5b"
>
>         run_dump_test "note"
>
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/size-5.s
> @@ -0,0 +1,32 @@
> +       .text
> +size:
> +       mov     $size@size, %eax
> +       mov     $size@size + val, %eax
> +       mov     $-size@size, %ecx
> +       mov     $0 - size@size, %ecx
> +       mov     $0x100 - size@size, %edx
> +       mov     $val - size@size, %edx
> +
> +       lea     size@size, %eax
> +       lea     size@size + val, %eax
> +       lea     -size@size, %ecx
> +       lea     0 - size@size, %ecx
> +       lea     0x100 - size@size, %edx
> +       lea     val - size@size, %edx
> +
> +       ret
> +       .size size, . - size
> +
> +       .data
> +       .p2align 2
> +       .long   size@size
> +       .long   size@size + val
> +       .long   -size@size
> +       .long   0 - size@size
> +       .long   0x100 - size@size
> +       .long   val - size@size
> +
> +       .long   ext@size
> +       .long   ext@size + val
> +
> +       .equ val, 0x1000
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/size-5a.d
> @@ -0,0 +1,25 @@
> +#name: i386 size 5 (text)
> +#source: size-5.s
> +#objdump: -dwr
> +
> +
> +.*: +file format .*
> +
> +
> +Disassembly of section .text:
> +
> +0+ <size>:
> +[      ]*[a-f0-9]+:    b8 43 00 00 00          mov    \$0x43,%eax
> +[      ]*[a-f0-9]+:    b8 43 10 00 00          mov    \$0x1043,%eax
> +[      ]*[a-f0-9]+:    b9 bd ff ff ff          mov    \$0xffffffbd,%ecx
> +[      ]*[a-f0-9]+:    b9 bd ff ff ff          mov    \$0xffffffbd,%ecx
> +[      ]*[a-f0-9]+:    ba bd 00 00 00          mov    \$0xbd,%edx
> +[      ]*[a-f0-9]+:    ba bd 0f 00 00          mov    \$0xfbd,%edx
> +[      ]*[a-f0-9]+:    8d 05 43 00 00 00       lea    0x43,%eax
> +[      ]*[a-f0-9]+:    8d 05 43 10 00 00       lea    0x1043,%eax
> +[      ]*[a-f0-9]+:    8d 0d bd ff ff ff       lea    0xffffffbd,%ecx
> +[      ]*[a-f0-9]+:    8d 0d bd ff ff ff       lea    0xffffffbd,%ecx
> +[      ]*[a-f0-9]+:    8d 15 bd 00 00 00       lea    0xbd,%edx
> +[      ]*[a-f0-9]+:    8d 15 bd 0f 00 00       lea    0xfbd,%edx
> +[      ]*[a-f0-9]+:    c3                      ret *
> +#pass
> --- /dev/null
> +++ b/gas/testsuite/gas/i386/size-5b.d
> @@ -0,0 +1,15 @@
> +#name: i386 size 5 (data)
> +#source: size-5.s
> +#objdump: -rsj .data
> +
> +.*: +file format .*
> +
> +RELOCATION RECORDS FOR \[\.data\]:
> +
> +OFFSET +TYPE +VALUE *
> +0*18 R_386_SIZE32 *ext
> +0*1c R_386_SIZE32 *ext
> +
> +Contents of section .data:
> + 0+00 43 ?00 ?00 ?00 43 ?10 ?00 ?00 bd ?ff ?ff ?ff bd ?ff ?ff ?ff .*
> + 0+10 bd ?00 ?00 ?00 bd ?0f ?00 ?00 00 ?00 ?00 ?00 00 ?10 ?00 ?00 .*
>

Please verify that the sizes of the symbols match the outputs of @size.

-- 
H.J.


More information about the Binutils mailing list