x86: relax when/how @size can be used

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().
This commit is contained in:
Jan Beulich
2021-04-29 11:45:10 +02:00
parent 44f871628c
commit 3abbafc2aa
7 changed files with 138 additions and 9 deletions

View File

@ -1,3 +1,17 @@
2021-04-29 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.
2021-04-29 Jan Beulich <jbeulich@suse.com>
* config/tc-i386.c (tc_gen_reloc): Use section size for section

View File

@ -14173,9 +14173,17 @@ i386_cons_align (int ignore ATTRIBUTE_UNUSED)
}
}
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)
@ -14222,6 +14230,8 @@ i386_validate_fix (fixS *fixp)
}
}
#endif
return 1;
}
arelent *
@ -14233,18 +14243,38 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
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
@ -14256,6 +14286,12 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
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. */

View File

@ -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 *);

View File

@ -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"

View File

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

View File

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

View File

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