[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