aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@suse.com>2021-04-29 11:45:10 +0200
committerJan Beulich <jbeulich@suse.com>2021-04-29 11:45:10 +0200
commit3abbafc2aacc6706fea3e3e326e2f08d107c3672 (patch)
tree8762f858f41c93ef736b2fef06a8b5afc07d83de /gas
parent44f871628ccfcfd931f4619c60554f3bd6b57b8d (diff)
downloadgdb-3abbafc2aacc6706fea3e3e326e2f08d107c3672.zip
gdb-3abbafc2aacc6706fea3e3e326e2f08d107c3672.tar.gz
gdb-3abbafc2aacc6706fea3e3e326e2f08d107c3672.tar.bz2
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().
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog14
-rw-r--r--gas/config/tc-i386.c50
-rw-r--r--gas/config/tc-i386.h6
-rw-r--r--gas/testsuite/gas/i386/i386.exp2
-rw-r--r--gas/testsuite/gas/i386/size-5.s32
-rw-r--r--gas/testsuite/gas/i386/size-5a.d28
-rw-r--r--gas/testsuite/gas/i386/size-5b.d15
7 files changed, 138 insertions, 9 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index e36170a..a44b880 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,19 @@
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
symbols when resolving BFD_RELOC_SIZE*.
* testsuite/gas/i386/size-2.s: Add section size cases.
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 9c544ee..8bd725a 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -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. */
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index 39d7c27..5516a16 100644
--- 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 *);
diff --git a/gas/testsuite/gas/i386/i386.exp b/gas/testsuite/gas/i386/i386.exp
index 1846c98..ae01c89 100644
--- 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"
diff --git a/gas/testsuite/gas/i386/size-5.s b/gas/testsuite/gas/i386/size-5.s
new file mode 100644
index 0000000..a870c28
--- /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
diff --git a/gas/testsuite/gas/i386/size-5a.d b/gas/testsuite/gas/i386/size-5a.d
new file mode 100644
index 0000000..56d0342
--- /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
diff --git a/gas/testsuite/gas/i386/size-5b.d b/gas/testsuite/gas/i386/size-5b.d
new file mode 100644
index 0000000..8439801
--- /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 .*