diff options
author | Jan Beulich <jbeulich@suse.com> | 2021-04-29 11:45:10 +0200 |
---|---|---|
committer | Jan Beulich <jbeulich@suse.com> | 2021-04-29 11:45:10 +0200 |
commit | 3abbafc2aacc6706fea3e3e326e2f08d107c3672 (patch) | |
tree | 8762f858f41c93ef736b2fef06a8b5afc07d83de /gas/config | |
parent | 44f871628ccfcfd931f4619c60554f3bd6b57b8d (diff) | |
download | gdb-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/config')
-rw-r--r-- | gas/config/tc-i386.c | 50 | ||||
-rw-r--r-- | gas/config/tc-i386.h | 6 |
2 files changed, 47 insertions, 9 deletions
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 *); |