summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2019-07-30 02:07:35 -0700
committerH. Peter Anvin <hpa@zytor.com>2019-07-30 02:07:35 -0700
commit8b129029f619a2b764f511bfc01ac85f4c22c279 (patch)
tree930a22238a9b40af5504065a6423fe11d3e0a924
parentcd5ea1c0f3d25621fc9a725f82c18d007397cddd (diff)
downloadbinutils-8b129029f619a2b764f511bfc01ac85f4c22c279.tar.gz
binutils-8b129029f619a2b764f511bfc01ac85f4c22c279.tar.xz
binutils-8b129029f619a2b764f511bfc01ac85f4c22c279.zip
gas, i386: support generating R_386_SUB16 and R_386_SUB32 relocations
R_386_SUB16 and R_386_SUB32 relocations can now be generated naturally by specifying two symbols being subtracted: mov $(foo - bar),%eax Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--gas/config/tc-i386.c58
-rw-r--r--gas/config/tc-i386.h6
2 files changed, 57 insertions, 7 deletions
diff --git a/gas/config/tc-i386.c b/gas/config/tc-i386.c
index 1274fbbaa8..6744fb6092 100644
--- a/gas/config/tc-i386.c
+++ b/gas/config/tc-i386.c
@@ -5273,7 +5273,7 @@ optimize_disp (void)
i.types[op].bitfield.disp32s = 0;
i.types[op].bitfield.disp64 = 0;
}
- else
+ else
/* We only support 64bit displacement on constants. */
i.types[op].bitfield.disp64 = 0;
}
@@ -9065,7 +9065,7 @@ lex_got (enum bfd_reloc_code_real *rel ATTRIBUTE_UNUSED,
gotrel[j].str, 1 << (5 + object_64bit));
return NULL;
}
-
+
*rel = gotrel[j].rel[object_64bit];
if (adjust)
*adjust = len;
@@ -12020,6 +12020,21 @@ s_bss (int ignore ATTRIBUTE_UNUSED)
#endif
+#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
+int
+i386_elf_validate_fix_sub (fixS *fixp, segT seg)
+{
+ if (seg == reg_section)
+ return FALSE;
+
+ if (IS_ELF && !object_64bit)
+ return TRUE;
+
+ return fixp->fx_r_type == BFD_RELOC_GPREL32
+ || fixp->fx_r_type == BFD_RELOC_GPREL16;
+}
+#endif
+
void
i386_validate_fix (fixS *fixp)
{
@@ -12060,12 +12075,15 @@ i386_validate_fix (fixS *fixp)
#endif
}
-arelent *
+arelent **
tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
{
- arelent *rel;
+ static arelent *relocs[MAX_RELOC_EXPANSION+1];
+ arelent *rel, **relp;
bfd_reloc_code_real_type code;
+ relp = &relocs[0];
+
switch (fixp->fx_r_type)
{
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
@@ -12084,7 +12102,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
fixp->fx_addsy = NULL;
fixp->fx_subsy = NULL;
md_apply_fix (fixp, (valueT *) &value, NULL);
- return NULL;
+ return relocs;
}
#endif
/* Fall through. */
@@ -12200,7 +12218,7 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
code = BFD_RELOC_X86_64_GOTPC64;
}
- rel = XNEW (arelent);
+ *relp++ = rel = XNEW (arelent);
rel->sym_ptr_ptr = XNEW (asymbol *);
*rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
@@ -12279,7 +12297,33 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
gas_assert (rel->howto != NULL);
}
- return rel;
+ if (fixp->fx_subsy)
+ {
+ switch (fixp->fx_size)
+ {
+ default:
+ as_bad_where (fixp->fx_file, fixp->fx_line,
+ _("can not do %d byte subtraction relocation"),
+ fixp->fx_size);
+ code = 0;
+ break;
+ case 2: code = BFD_RELOC_386_SUB16; break;
+ case 4: code = BFD_RELOC_386_SUB32; break;
+ }
+
+ if (code)
+ {
+ *relp++ = rel = XNEW (arelent);
+ rel->sym_ptr_ptr = XNEW (asymbol *);
+ *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
+ rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
+ rel->howto = bfd_reloc_type_lookup (stdoutput, code);
+ gas_assert (rel->howto != NULL);
+ }
+ }
+
+ *relp = NULL;
+ return relocs;
}
#include "tc-i386-intel.c"
diff --git a/gas/config/tc-i386.h b/gas/config/tc-i386.h
index b02a25671f..ef667d2fa4 100644
--- a/gas/config/tc-i386.h
+++ b/gas/config/tc-i386.h
@@ -325,8 +325,14 @@ extern bfd_vma x86_64_section_letter (int, const char **);
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
extern void x86_cleanup (void);
#define md_cleanup() x86_cleanup ()
+
+extern int i386_elf_validate_fix_sub (struct fix *, segT);
+#define TC_VALIDATE_FIX_SUB i386_elf_validate_fix_sub
#endif
+#define RELOC_EXPANSION_POSSIBLE 1
+#define MAX_RELOC_EXPANSION 2
+
#ifdef TE_PE
#define O_secrel O_md1