[v2,2/2] x86: relax when/how @size can be used

Message ID b9cf4b63-34ec-10a4-93b4-7454be8a9dc3@suse.com
State New
Headers show
Series
  • x86: assorted relocation handling related adjustments (part II)
Related show

Commit Message

Jan Beulich via Binutils April 28, 2021, 8:57 a.m.
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.
---
v2: Add -t to objdump options of size5a test case.
---
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.

Comments

Jan Beulich via Binutils April 28, 2021, 11:57 a.m. | #1
On Wed, Apr 28, 2021 at 3:23 AM Jan Beulich via Binutils
<binutils@sourceware.org> 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.

> ---

> v2: Add -t to objdump options of size5a test case.

> ---

> 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,28 @@

> +#name: i386 size 5 (text)

> +#source: size-5.s

> +#objdump: -dtwr

> +

> +.*: +file format .*

> +

> +SYMBOL TABLE:

> +0*0 l +\.text  0*43 size

> +0*1000 l +\*ABS\*      0*0 val

> +0*0 +\*UND\*   0*0 ext

> +

> +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 .*

>


OK.

Thanks.

-- 
H.J.

Patch

--- 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,28 @@ 
+#name: i386 size 5 (text)
+#source: size-5.s
+#objdump: -dtwr
+
+.*: +file format .*
+
+SYMBOL TABLE:
+0*0 l +\.text	0*43 size
+0*1000 l +\*ABS\*	0*0 val
+0*0 +\*UND\*	0*0 ext
+
+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 .*