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

Jan Beulich jbeulich@suse.com
Fri Apr 23 08:38:00 GMT 2021


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



More information about the Binutils mailing list