1999-05-03 15:29:11 +08:00
|
|
|
/* tc-i386.h -- Header file for tc-i386.c
|
2024-01-04 19:52:08 +08:00
|
|
|
Copyright (C) 1989-2024 Free Software Foundation, Inc.
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
This file is part of GAS, the GNU Assembler.
|
|
|
|
|
|
|
|
GAS is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2007-07-03 19:01:12 +08:00
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
1999-05-03 15:29:11 +08:00
|
|
|
any later version.
|
|
|
|
|
|
|
|
GAS is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GAS; see the file COPYING. If not, write to the Free
|
2005-05-05 17:13:19 +08:00
|
|
|
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
|
|
|
02110-1301, USA. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
#ifndef TC_I386
|
|
|
|
#define TC_I386 1
|
|
|
|
|
2007-03-21 23:37:21 +08:00
|
|
|
#include "opcodes/i386-opc.h"
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
struct fix;
|
|
|
|
|
|
|
|
#define TARGET_BYTES_BIG_ENDIAN 0
|
|
|
|
|
2009-07-25 22:58:58 +08:00
|
|
|
#define TARGET_ARCH (i386_arch ())
|
2001-01-14 07:37:57 +08:00
|
|
|
#define TARGET_MACH (i386_mach ())
|
2009-07-25 22:58:58 +08:00
|
|
|
extern enum bfd_architecture i386_arch (void);
|
2004-10-01 16:38:35 +08:00
|
|
|
extern unsigned long i386_mach (void);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2001-02-19 14:40:29 +08:00
|
|
|
#ifdef TE_FreeBSD
|
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386-freebsd"
|
|
|
|
#endif
|
1999-05-03 15:29:11 +08:00
|
|
|
#ifdef TE_NetBSD
|
2000-01-27 06:48:31 +08:00
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386-netbsd"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
#ifdef TE_386BSD
|
2000-01-27 06:48:31 +08:00
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386-bsd"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
#ifdef TE_LINUX
|
2000-01-27 06:48:31 +08:00
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386-linux"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
#ifdef TE_Mach
|
2000-01-27 06:48:31 +08:00
|
|
|
#define AOUT_TARGET_FORMAT "a.out-mach3"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
#ifdef TE_DYNIX
|
2000-01-27 06:48:31 +08:00
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386-dynix"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
2000-01-27 06:48:31 +08:00
|
|
|
#ifndef AOUT_TARGET_FORMAT
|
|
|
|
#define AOUT_TARGET_FORMAT "a.out-i386"
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
|
2002-09-17 10:24:40 +08:00
|
|
|
#ifdef TE_FreeBSD
|
|
|
|
#define ELF_TARGET_FORMAT "elf32-i386-freebsd"
|
2006-08-03 00:25:14 +08:00
|
|
|
#define ELF_TARGET_FORMAT64 "elf64-x86-64-freebsd"
|
2005-05-05 22:37:27 +08:00
|
|
|
#elif defined (TE_VXWORKS)
|
|
|
|
#define ELF_TARGET_FORMAT "elf32-i386-vxworks"
|
2019-04-08 15:27:51 +08:00
|
|
|
#elif defined TE_CLOUDABI
|
|
|
|
#define ELF_TARGET_FORMAT64 "elf64-x86-64-cloudabi"
|
2002-09-17 10:24:40 +08:00
|
|
|
#endif
|
2005-05-05 22:37:27 +08:00
|
|
|
|
2010-03-08 22:07:45 +08:00
|
|
|
#ifdef TE_SOLARIS
|
|
|
|
#define ELF_TARGET_FORMAT "elf32-i386-sol2"
|
|
|
|
#define ELF_TARGET_FORMAT64 "elf64-x86-64-sol2"
|
|
|
|
#endif
|
|
|
|
|
2002-09-17 10:24:40 +08:00
|
|
|
#ifndef ELF_TARGET_FORMAT
|
|
|
|
#define ELF_TARGET_FORMAT "elf32-i386"
|
|
|
|
#endif
|
|
|
|
|
2006-08-03 00:25:14 +08:00
|
|
|
#ifndef ELF_TARGET_FORMAT64
|
|
|
|
#define ELF_TARGET_FORMAT64 "elf64-x86-64"
|
|
|
|
#endif
|
|
|
|
|
2010-12-31 08:33:36 +08:00
|
|
|
#ifndef ELF_TARGET_FORMAT32
|
|
|
|
#define ELF_TARGET_FORMAT32 "elf32-x86-64"
|
|
|
|
#endif
|
|
|
|
|
2015-05-12 02:11:19 +08:00
|
|
|
#ifndef ELF_TARGET_IAMCU_FORMAT
|
|
|
|
#define ELF_TARGET_IAMCU_FORMAT "elf32-iamcu"
|
|
|
|
#endif
|
|
|
|
|
2024-10-04 15:42:13 +08:00
|
|
|
#if (defined (OBJ_ELF) || defined (TE_PE) || defined (OBJ_MACH_O))
|
2007-01-04 06:36:19 +08:00
|
|
|
extern const char *i386_target_format (void);
|
2000-01-27 06:48:31 +08:00
|
|
|
#define TARGET_FORMAT i386_target_format ()
|
|
|
|
#else
|
2009-08-11 05:32:26 +08:00
|
|
|
#ifdef TE_GO32
|
|
|
|
#define TARGET_FORMAT "coff-go32"
|
|
|
|
#endif
|
2000-01-27 06:48:31 +08:00
|
|
|
#ifdef OBJ_AOUT
|
|
|
|
#define TARGET_FORMAT AOUT_TARGET_FORMAT
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
2002-05-23 16:08:48 +08:00
|
|
|
#define SUB_SEGMENT_ALIGN(SEG, FRCHAIN) 0
|
|
|
|
|
2009-03-10 02:33:42 +08:00
|
|
|
/* '$' may be used as immediate prefix. */
|
|
|
|
#undef LOCAL_LABELS_DOLLAR
|
|
|
|
#define LOCAL_LABELS_DOLLAR 0
|
|
|
|
#undef LOCAL_LABELS_FB
|
2002-08-09 20:37:41 +08:00
|
|
|
#define LOCAL_LABELS_FB 1
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
extern const char extra_symbol_chars[];
|
|
|
|
#define tc_symbol_chars extra_symbol_chars
|
|
|
|
|
2005-11-07 14:01:18 +08:00
|
|
|
extern const char *i386_comment_chars;
|
|
|
|
#define tc_comment_chars i386_comment_chars
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
/* The name of the global offset table generated by the compiler. Allow
|
2000-09-16 08:56:47 +08:00
|
|
|
this to be overridden if need be. */
|
1999-05-03 15:29:11 +08:00
|
|
|
#ifndef GLOBAL_OFFSET_TABLE_NAME
|
|
|
|
#define GLOBAL_OFFSET_TABLE_NAME "_GLOBAL_OFFSET_TABLE_"
|
|
|
|
#endif
|
|
|
|
|
2002-08-09 20:37:41 +08:00
|
|
|
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) x86_cons (EXP, NBYTES)
|
gas TC_PARSE_CONS_EXPRESSION communication with TC_CONS_FIX_NEW
A number of targets pass extra information from TC_PARSE_CONS_EXPRESSION
to TC_CONS_FIX_NEW via static variables. That's OK, but not best
practice. tc-ppc.c goes further in implementing its own replacement
for cons(), because the generic one doesn't allow relocation modifiers
on constants. This patch fixes both of these warts.
* gas/config/tc-alpha.h (TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arc.c (arc_cons_fix_new): Add reloc parameter.
* gas/config/tc-arc.h (arc_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arm.c (cons_fix_new_arm): Similarly
* gas/config/tc-arm.h (cons_fix_new_arm, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-cr16.c (cr16_cons_fix_new): Similarly.
* gas/config/tc-cr16.h (cr16_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-crx.h (TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-m32c.c (m32c_cons_fix_new): Similarly.
* gas/config/tc-m32c.h (m32c_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-mn10300.c (mn10300_cons_fix_new): Similarly.
* gas/config/tc-mn10300.h (mn10300_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-ns32k.c (cons_fix_new_ns32k): Similarly.
* gas/config/tc-ns32k.h (cons_fix_new_ns32k): Similarly.
* gas/config/tc-pj.c (pj_cons_fix_new_pj): Similarly.
* gas/config/tc-pj.h (pj_cons_fix_new_pj, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-rx.c (rx_cons_fix_new): Similarly.
* gas/config/tc-rx.h (rx_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-sh.c (sh_cons_fix_new): Similarly.
* gas/config/tc-sh.h (sh_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-tic54x.c (tic54x_cons_fix_new): Similarly.
* gas/config/tc-tic54x.h (tic54x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-tic6x.c (tic6x_cons_fix_new): Similarly.
* gas/config/tc-tic6x.h (tic6x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-arc.c (arc_parse_cons_expression): Return reloc.
* gas/config/tc-arc.h (arc_parse_cons_expression): Update proto.
* gas/config/tc-avr.c (exp_mod_data): Make global.
(pexp_mod_data): Delete.
(avr_parse_cons_expression): Return exp_mod_data pointer.
(avr_cons_fix_new): Add exp_mod_data_t pointer param.
(exp_mod_data_t): Move typedef..
* gas/config/tc-avr.h: ..to here.
(exp_mod_data): Declare.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
(avr_parse_cons_expression, avr_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Update.
* gas/config/tc-hppa.c (hppa_field_selector): Delete static var.
(cons_fix_new_hppa): Add hppa_field_selector param.
(fix_new_hppa): Adjust.
(parse_cons_expression_hppa): Return field selector.
* gas/config/tc-hppa.h (parse_cons_expression_hppa): Update proto.
(cons_fix_new_hppa): Likewise.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
* gas/config/tc-i386.c (got_reloc): Delete static var.
(x86_cons_fix_new): Add reloc param.
(x86_cons): Return got reloc.
* gas/config/tc-i386.h (x86_cons, x86_cons_fix_new): Update proto.
(TC_CONS_FIX_NEW): Add RELOC param.
* gas/config/tc-ia64.c (ia64_cons_fix_new): Add reloc param. Adjust
calls.
* gas/config/tc-ia64.h (ia64_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add reloc param.
* gas/config/tc-microblaze.c (parse_cons_expression_microblaze):
Return reloc.
(cons_fix_new_microblaze): Add reloc param.
* gas/config/tc-microblaze.h: Formatting.
(parse_cons_expression_microblaze): Update proto.
(cons_fix_new_microblaze): Likewise.
* gas/config/tc-nios2.c (nios2_tls_ldo_reloc): Delete static var.
(nios2_cons): Return ldo reloc.
(nios2_cons_fix_new): Delete.
* gas/config/tc-nios2.h (nios2_cons): Update prototype.
(nios2_cons_fix_new, TC_CONS_FIX_NEW): Delete.
* gas/config/tc-ppc.c (md_pseudo_table): Remove quad, long, word,
short. Make llong use cons.
(ppc_elf_suffix): Return BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(ppc_elf_cons): Delete.
(ppc_elf_parse_cons): New function.
(ppc_elf_validate_fix): Don't check for BFD_RELOC_UNUSED.
(md_assemble): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
* gas/config/tc-ppc.h (TC_PARSE_CONS_EXPRESSION): Define
(ppc_elf_parse_cons): Declare.
* gas/config/tc-sparc.c (sparc_cons_special_reloc): Delete static var.
(sparc_cons): Return reloc specifier.
(cons_fix_new_sparc): Add reloc specifier param.
(sparc_cfi_emit_pcrel_expr): Use emit_expr_with_reloc.
* gas/config/tc-sparc.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(sparc_cons, cons_fix_new_sparc): Update prototype.
* gas/config/tc-v850.c (hold_cons_reloc): Delete static var.
(v850_reloc_prefix): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(md_assemble): Likewise.
(parse_cons_expression_v850): Return reloc.
(cons_fix_new_v850): Add reloc parameter.
* gas/config/tc-v850.h (parse_cons_expression_v850): Update proto.
(cons_fix_new_v850): Likewise.
* gas/config/tc-vax.c (vax_cons_special_reloc): Delete static var.
(vax_cons): Return reloc.
(vax_cons_fix_new): Add reloc parameter.
* gas/config/tc-vax.h (vax_cons, vax_cons_fix_new): Update proto.
* gas/config/tc-xstormy16.c (xstormy16_cons_fix_new): Add reloc param.
* gas/config/tc-xstormy16.h (xstormy16_cons_fix_new): Update proto.
* gas/dwarf2dbg.c (TC_PARSE_CONS_RETURN_NONE): Provide default.
(emit_fixed_inc_line_addr): Adjust exmit_expr_fix calls.
* gas/read.c (TC_PARSE_CONS_EXPRESSION): Return value.
(do_parse_cons_expression): Adjust.
(cons_worker): Pass return value from TC_PARSE_CONS_EXPRESSION
to emit_expr_with_reloc.
(emit_expr_with_reloc): New function handling reloc, mostly
extracted from..
(emit_expr): ..here.
(emit_expr_fix): Add reloc param. Adjust TC_CONS_FIX_NEW invocation.
Handle reloc.
(parse_mri_cons): Convert to ISO.
* gas/read.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(emit_expr_with_reloc): Declare.
(emit_expr_fix): Update prototype.
* gas/write.c (write_object_file): Update TC_CONS_FIX_NEW invocation.
2014-04-08 13:08:22 +08:00
|
|
|
extern bfd_reloc_code_real_type x86_cons (expressionS *, int);
|
2002-08-09 20:37:41 +08:00
|
|
|
|
gas TC_PARSE_CONS_EXPRESSION communication with TC_CONS_FIX_NEW
A number of targets pass extra information from TC_PARSE_CONS_EXPRESSION
to TC_CONS_FIX_NEW via static variables. That's OK, but not best
practice. tc-ppc.c goes further in implementing its own replacement
for cons(), because the generic one doesn't allow relocation modifiers
on constants. This patch fixes both of these warts.
* gas/config/tc-alpha.h (TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arc.c (arc_cons_fix_new): Add reloc parameter.
* gas/config/tc-arc.h (arc_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arm.c (cons_fix_new_arm): Similarly
* gas/config/tc-arm.h (cons_fix_new_arm, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-cr16.c (cr16_cons_fix_new): Similarly.
* gas/config/tc-cr16.h (cr16_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-crx.h (TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-m32c.c (m32c_cons_fix_new): Similarly.
* gas/config/tc-m32c.h (m32c_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-mn10300.c (mn10300_cons_fix_new): Similarly.
* gas/config/tc-mn10300.h (mn10300_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-ns32k.c (cons_fix_new_ns32k): Similarly.
* gas/config/tc-ns32k.h (cons_fix_new_ns32k): Similarly.
* gas/config/tc-pj.c (pj_cons_fix_new_pj): Similarly.
* gas/config/tc-pj.h (pj_cons_fix_new_pj, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-rx.c (rx_cons_fix_new): Similarly.
* gas/config/tc-rx.h (rx_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-sh.c (sh_cons_fix_new): Similarly.
* gas/config/tc-sh.h (sh_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-tic54x.c (tic54x_cons_fix_new): Similarly.
* gas/config/tc-tic54x.h (tic54x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-tic6x.c (tic6x_cons_fix_new): Similarly.
* gas/config/tc-tic6x.h (tic6x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-arc.c (arc_parse_cons_expression): Return reloc.
* gas/config/tc-arc.h (arc_parse_cons_expression): Update proto.
* gas/config/tc-avr.c (exp_mod_data): Make global.
(pexp_mod_data): Delete.
(avr_parse_cons_expression): Return exp_mod_data pointer.
(avr_cons_fix_new): Add exp_mod_data_t pointer param.
(exp_mod_data_t): Move typedef..
* gas/config/tc-avr.h: ..to here.
(exp_mod_data): Declare.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
(avr_parse_cons_expression, avr_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Update.
* gas/config/tc-hppa.c (hppa_field_selector): Delete static var.
(cons_fix_new_hppa): Add hppa_field_selector param.
(fix_new_hppa): Adjust.
(parse_cons_expression_hppa): Return field selector.
* gas/config/tc-hppa.h (parse_cons_expression_hppa): Update proto.
(cons_fix_new_hppa): Likewise.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
* gas/config/tc-i386.c (got_reloc): Delete static var.
(x86_cons_fix_new): Add reloc param.
(x86_cons): Return got reloc.
* gas/config/tc-i386.h (x86_cons, x86_cons_fix_new): Update proto.
(TC_CONS_FIX_NEW): Add RELOC param.
* gas/config/tc-ia64.c (ia64_cons_fix_new): Add reloc param. Adjust
calls.
* gas/config/tc-ia64.h (ia64_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add reloc param.
* gas/config/tc-microblaze.c (parse_cons_expression_microblaze):
Return reloc.
(cons_fix_new_microblaze): Add reloc param.
* gas/config/tc-microblaze.h: Formatting.
(parse_cons_expression_microblaze): Update proto.
(cons_fix_new_microblaze): Likewise.
* gas/config/tc-nios2.c (nios2_tls_ldo_reloc): Delete static var.
(nios2_cons): Return ldo reloc.
(nios2_cons_fix_new): Delete.
* gas/config/tc-nios2.h (nios2_cons): Update prototype.
(nios2_cons_fix_new, TC_CONS_FIX_NEW): Delete.
* gas/config/tc-ppc.c (md_pseudo_table): Remove quad, long, word,
short. Make llong use cons.
(ppc_elf_suffix): Return BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(ppc_elf_cons): Delete.
(ppc_elf_parse_cons): New function.
(ppc_elf_validate_fix): Don't check for BFD_RELOC_UNUSED.
(md_assemble): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
* gas/config/tc-ppc.h (TC_PARSE_CONS_EXPRESSION): Define
(ppc_elf_parse_cons): Declare.
* gas/config/tc-sparc.c (sparc_cons_special_reloc): Delete static var.
(sparc_cons): Return reloc specifier.
(cons_fix_new_sparc): Add reloc specifier param.
(sparc_cfi_emit_pcrel_expr): Use emit_expr_with_reloc.
* gas/config/tc-sparc.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(sparc_cons, cons_fix_new_sparc): Update prototype.
* gas/config/tc-v850.c (hold_cons_reloc): Delete static var.
(v850_reloc_prefix): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(md_assemble): Likewise.
(parse_cons_expression_v850): Return reloc.
(cons_fix_new_v850): Add reloc parameter.
* gas/config/tc-v850.h (parse_cons_expression_v850): Update proto.
(cons_fix_new_v850): Likewise.
* gas/config/tc-vax.c (vax_cons_special_reloc): Delete static var.
(vax_cons): Return reloc.
(vax_cons_fix_new): Add reloc parameter.
* gas/config/tc-vax.h (vax_cons, vax_cons_fix_new): Update proto.
* gas/config/tc-xstormy16.c (xstormy16_cons_fix_new): Add reloc param.
* gas/config/tc-xstormy16.h (xstormy16_cons_fix_new): Update proto.
* gas/dwarf2dbg.c (TC_PARSE_CONS_RETURN_NONE): Provide default.
(emit_fixed_inc_line_addr): Adjust exmit_expr_fix calls.
* gas/read.c (TC_PARSE_CONS_EXPRESSION): Return value.
(do_parse_cons_expression): Adjust.
(cons_worker): Pass return value from TC_PARSE_CONS_EXPRESSION
to emit_expr_with_reloc.
(emit_expr_with_reloc): New function handling reloc, mostly
extracted from..
(emit_expr): ..here.
(emit_expr_fix): Add reloc param. Adjust TC_CONS_FIX_NEW invocation.
Handle reloc.
(parse_mri_cons): Convert to ISO.
* gas/read.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(emit_expr_with_reloc): Declare.
(emit_expr_fix): Update prototype.
* gas/write.c (write_object_file): Update TC_CONS_FIX_NEW invocation.
2014-04-08 13:08:22 +08:00
|
|
|
#define TC_CONS_FIX_NEW(FRAG, OFF, LEN, EXP, RELOC) \
|
|
|
|
x86_cons_fix_new(FRAG, OFF, LEN, EXP, RELOC)
|
2002-08-09 20:37:41 +08:00
|
|
|
extern void x86_cons_fix_new
|
gas TC_PARSE_CONS_EXPRESSION communication with TC_CONS_FIX_NEW
A number of targets pass extra information from TC_PARSE_CONS_EXPRESSION
to TC_CONS_FIX_NEW via static variables. That's OK, but not best
practice. tc-ppc.c goes further in implementing its own replacement
for cons(), because the generic one doesn't allow relocation modifiers
on constants. This patch fixes both of these warts.
* gas/config/tc-alpha.h (TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arc.c (arc_cons_fix_new): Add reloc parameter.
* gas/config/tc-arc.h (arc_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add RELOC parameter.
* gas/config/tc-arm.c (cons_fix_new_arm): Similarly
* gas/config/tc-arm.h (cons_fix_new_arm, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-cr16.c (cr16_cons_fix_new): Similarly.
* gas/config/tc-cr16.h (cr16_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-crx.h (TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-m32c.c (m32c_cons_fix_new): Similarly.
* gas/config/tc-m32c.h (m32c_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-mn10300.c (mn10300_cons_fix_new): Similarly.
* gas/config/tc-mn10300.h (mn10300_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-ns32k.c (cons_fix_new_ns32k): Similarly.
* gas/config/tc-ns32k.h (cons_fix_new_ns32k): Similarly.
* gas/config/tc-pj.c (pj_cons_fix_new_pj): Similarly.
* gas/config/tc-pj.h (pj_cons_fix_new_pj, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-rx.c (rx_cons_fix_new): Similarly.
* gas/config/tc-rx.h (rx_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-sh.c (sh_cons_fix_new): Similarly.
* gas/config/tc-sh.h (sh_cons_fix_new, TC_CONS_FIX_NEW): Similarly.
* gas/config/tc-tic54x.c (tic54x_cons_fix_new): Similarly.
* gas/config/tc-tic54x.h (tic54x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-tic6x.c (tic6x_cons_fix_new): Similarly.
* gas/config/tc-tic6x.h (tic6x_cons_fix_new, TC_CONS_FIX_NEW):
Similarly.
* gas/config/tc-arc.c (arc_parse_cons_expression): Return reloc.
* gas/config/tc-arc.h (arc_parse_cons_expression): Update proto.
* gas/config/tc-avr.c (exp_mod_data): Make global.
(pexp_mod_data): Delete.
(avr_parse_cons_expression): Return exp_mod_data pointer.
(avr_cons_fix_new): Add exp_mod_data_t pointer param.
(exp_mod_data_t): Move typedef..
* gas/config/tc-avr.h: ..to here.
(exp_mod_data): Declare.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
(avr_parse_cons_expression, avr_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Update.
* gas/config/tc-hppa.c (hppa_field_selector): Delete static var.
(cons_fix_new_hppa): Add hppa_field_selector param.
(fix_new_hppa): Adjust.
(parse_cons_expression_hppa): Return field selector.
* gas/config/tc-hppa.h (parse_cons_expression_hppa): Update proto.
(cons_fix_new_hppa): Likewise.
(TC_PARSE_CONS_RETURN_TYPE, TC_PARSE_CONS_RETURN_NONE): Define.
* gas/config/tc-i386.c (got_reloc): Delete static var.
(x86_cons_fix_new): Add reloc param.
(x86_cons): Return got reloc.
* gas/config/tc-i386.h (x86_cons, x86_cons_fix_new): Update proto.
(TC_CONS_FIX_NEW): Add RELOC param.
* gas/config/tc-ia64.c (ia64_cons_fix_new): Add reloc param. Adjust
calls.
* gas/config/tc-ia64.h (ia64_cons_fix_new): Update prototype.
(TC_CONS_FIX_NEW): Add reloc param.
* gas/config/tc-microblaze.c (parse_cons_expression_microblaze):
Return reloc.
(cons_fix_new_microblaze): Add reloc param.
* gas/config/tc-microblaze.h: Formatting.
(parse_cons_expression_microblaze): Update proto.
(cons_fix_new_microblaze): Likewise.
* gas/config/tc-nios2.c (nios2_tls_ldo_reloc): Delete static var.
(nios2_cons): Return ldo reloc.
(nios2_cons_fix_new): Delete.
* gas/config/tc-nios2.h (nios2_cons): Update prototype.
(nios2_cons_fix_new, TC_CONS_FIX_NEW): Delete.
* gas/config/tc-ppc.c (md_pseudo_table): Remove quad, long, word,
short. Make llong use cons.
(ppc_elf_suffix): Return BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(ppc_elf_cons): Delete.
(ppc_elf_parse_cons): New function.
(ppc_elf_validate_fix): Don't check for BFD_RELOC_UNUSED.
(md_assemble): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
* gas/config/tc-ppc.h (TC_PARSE_CONS_EXPRESSION): Define
(ppc_elf_parse_cons): Declare.
* gas/config/tc-sparc.c (sparc_cons_special_reloc): Delete static var.
(sparc_cons): Return reloc specifier.
(cons_fix_new_sparc): Add reloc specifier param.
(sparc_cfi_emit_pcrel_expr): Use emit_expr_with_reloc.
* gas/config/tc-sparc.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(sparc_cons, cons_fix_new_sparc): Update prototype.
* gas/config/tc-v850.c (hold_cons_reloc): Delete static var.
(v850_reloc_prefix): Use BFD_RELOC_NONE rather than BFD_RELOC_UNUSED.
(md_assemble): Likewise.
(parse_cons_expression_v850): Return reloc.
(cons_fix_new_v850): Add reloc parameter.
* gas/config/tc-v850.h (parse_cons_expression_v850): Update proto.
(cons_fix_new_v850): Likewise.
* gas/config/tc-vax.c (vax_cons_special_reloc): Delete static var.
(vax_cons): Return reloc.
(vax_cons_fix_new): Add reloc parameter.
* gas/config/tc-vax.h (vax_cons, vax_cons_fix_new): Update proto.
* gas/config/tc-xstormy16.c (xstormy16_cons_fix_new): Add reloc param.
* gas/config/tc-xstormy16.h (xstormy16_cons_fix_new): Update proto.
* gas/dwarf2dbg.c (TC_PARSE_CONS_RETURN_NONE): Provide default.
(emit_fixed_inc_line_addr): Adjust exmit_expr_fix calls.
* gas/read.c (TC_PARSE_CONS_EXPRESSION): Return value.
(do_parse_cons_expression): Adjust.
(cons_worker): Pass return value from TC_PARSE_CONS_EXPRESSION
to emit_expr_with_reloc.
(emit_expr_with_reloc): New function handling reloc, mostly
extracted from..
(emit_expr): ..here.
(emit_expr_fix): Add reloc param. Adjust TC_CONS_FIX_NEW invocation.
Handle reloc.
(parse_mri_cons): Convert to ISO.
* gas/read.h (TC_PARSE_CONS_RETURN_TYPE): Define.
(TC_PARSE_CONS_RETURN_NONE): Define.
(emit_expr_with_reloc): Declare.
(emit_expr_fix): Update prototype.
* gas/write.c (write_object_file): Update TC_CONS_FIX_NEW invocation.
2014-04-08 13:08:22 +08:00
|
|
|
(fragS *, unsigned int, unsigned int, expressionS *, bfd_reloc_code_real_type);
|
2002-08-09 20:37:41 +08:00
|
|
|
|
2021-08-11 14:31:03 +08:00
|
|
|
#define X_PRECISION 5
|
2021-08-16 04:17:41 +08:00
|
|
|
#define X_PRECISION_PAD 0
|
2021-08-11 14:30:26 +08:00
|
|
|
|
2012-06-14 05:41:07 +08:00
|
|
|
#define TC_ADDRESS_BYTES x86_address_bytes
|
|
|
|
extern int x86_address_bytes (void);
|
|
|
|
|
2002-08-09 20:37:41 +08:00
|
|
|
#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs */
|
|
|
|
|
|
|
|
#define NO_RELOC BFD_RELOC_NONE
|
|
|
|
|
2021-04-29 17:45:10 +08:00
|
|
|
int i386_validate_fix (struct fix *);
|
|
|
|
#define TC_VALIDATE_FIX(FIX,SEGTYPE,SKIP) do { \
|
|
|
|
if (!i386_validate_fix(FIX)) goto SKIP; \
|
|
|
|
} while (0)
|
2002-08-09 20:37:41 +08:00
|
|
|
|
2024-10-04 15:42:13 +08:00
|
|
|
#ifdef OBJ_ELF
|
2002-08-09 20:37:41 +08:00
|
|
|
#define tc_fix_adjustable(X) tc_i386_fix_adjustable(X)
|
2007-01-04 06:36:19 +08:00
|
|
|
extern int tc_i386_fix_adjustable (struct fix *);
|
2023-11-17 18:20:49 +08:00
|
|
|
#else
|
|
|
|
#define tc_fix_adjustable(X) ((void)(X), 1)
|
|
|
|
#endif
|
2002-08-09 20:37:41 +08:00
|
|
|
|
gas:
* cgen.c, cgen.h, tc.h, write.c, config/obj-coff.c
* config/tc-a29k.c, config/tc-alpha.c, config/tc-alpha.h
* config/tc-arc.c, config/tc-arc.h, config/tc-arm.c
* config/tc-arm.h, config/tc-avr.c, config/tc-avr.h
* config/tc-cris.c, config/tc-crx.c, config/tc-d10v.c
* config/tc-d10v.h, config/tc-d30v.c, config/tc-d30v.h
* config/tc-dlx.c, config/tc-dlx.h, config/tc-fr30.h
* config/tc-frv.c, config/tc-frv.h, config/tc-h8300.c
* config/tc-h8500.c, config/tc-hppa.c, config/tc-hppa.h
* config/tc-i370.c, config/tc-i370.h, config/tc-i386.c
* config/tc-i386.h, config/tc-i860.c, config/tc-i860.h
* config/tc-i960.c, config/tc-i960.h, config/tc-ia64.c
* config/tc-ip2k.c, config/tc-ip2k.h, config/tc-iq2000.c
* config/tc-iq2000.h, config/tc-m32r.c, config/tc-m32r.h
* config/tc-m68hc11.c, config/tc-m68hc11.h, config/tc-m68k.c
* config/tc-m68k.h, config/tc-m88k.c, config/tc-maxq.c
* config/tc-mcore.c, config/tc-mcore.h, config/tc-mips.c
* config/tc-mips.h, config/tc-mmix.c, config/tc-mn10200.c
* config/tc-mn10300.c, config/tc-msp430.c, config/tc-ns32k.c
* config/tc-openrisc.h, config/tc-or32.c, config/tc-or32.h
* config/tc-pdp11.c, config/tc-pj.c, config/tc-pj.h
* config/tc-ppc.c, config/tc-ppc.h, config/tc-s390.c
* config/tc-s390.h, config/tc-sh64.c, config/tc-sh.c
* config/tc-sh.h, config/tc-sparc.c, config/tc-sparc.h
* config/tc-tahoe.c, config/tc-tic30.c, config/tc-tic4x.c
* config/tc-tic54x.c, config/tc-tic80.c, config/tc-v850.c
* config/tc-v850.h, config/tc-vax.c, config/tc-vax.h
* config/tc-w65.c, config/tc-xstormy16.c, config/tc-xstormy16.h
* config/tc-xtensa.c, config/tc-z8k.c:
Replace all instances of the string "_apply_fix3" with
"_apply_fix".
* po/POTFILES.in, po/gas.pot: Regenerate.
bfd:
* coff-i386.c: Change md_apply_fix3 to md_apply_fix in comment.
cgen:
* doc/porting.texi: Change all mention of md_apply_fix3 and
gas_cgen_md_apply_fix3 to md_apply_fix and gas_cgen_md_apply_fix
respectively.
2005-06-08 01:54:22 +08:00
|
|
|
/* Values passed to md_apply_fix don't include the symbol value. */
|
2002-09-05 08:01:18 +08:00
|
|
|
#define MD_APPLY_SYM_VALUE(FIX) 0
|
2002-10-15 10:20:53 +08:00
|
|
|
|
|
|
|
/* ELF wants external syms kept, as does PE COFF. */
|
2003-01-23 20:51:05 +08:00
|
|
|
#if defined (TE_PE) && defined (STRICT_PE_FORMAT)
|
|
|
|
#define EXTERN_FORCE_RELOC \
|
2023-11-17 18:21:13 +08:00
|
|
|
(IS_ELF || OUTPUT_FLAVOR == bfd_target_coff_flavour)
|
2002-10-15 10:20:53 +08:00
|
|
|
#else
|
2023-11-17 18:21:13 +08:00
|
|
|
#define EXTERN_FORCE_RELOC IS_ELF
|
1999-05-03 15:29:11 +08:00
|
|
|
#endif
|
|
|
|
|
2002-09-05 08:01:18 +08:00
|
|
|
/* This expression evaluates to true if the relocation is for a local
|
|
|
|
object for which we still want to do the relocation at runtime.
|
|
|
|
False if we are willing to perform this relocation while building
|
2012-01-24 05:42:04 +08:00
|
|
|
the .o file. GOTOFF and GOT32 do not need to be checked here because
|
2009-09-24 11:23:52 +08:00
|
|
|
they are not pcrel. .*/
|
2002-08-09 20:37:41 +08:00
|
|
|
|
Add R_X86_64_[REX_]GOTPCRELX support to gas and ld
This patch adds support for the R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX relocations proposed in
https://groups.google.com/forum/#!topic/x86-64-abi/n9AWHogmVY0
to gas and ld. It updates gas to generate R_X86_64_GOTPCRELX,
R_X86_64_REX_GOTPCRELX if there is a REX prefix, relocation for memory
operand, foo@GOTPCREL(%rip). With the locally defined symbol, foo, we
convert
mov foo@GOTPCREL(%rip), %reg
to
lea foo(%rip), %reg
and convert
call/jmp *foo@GOTPCREL(%rip)
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg, foo@GOTPCREL(%rip)
to
test $foo, %reg
and convert
binop foo@GOTPCREL(%rip), %reg
to
binop $foo, %reg
where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions.
bfd/
* elf64-x86-64.c: Include opcode/i386.h.
(x86_64_elf_howto_table): Add R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(R_X86_64_standard): Replace R_X86_64_PLT32_BND with
R_X86_64_REX_GOTPCRELX.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
(need_convert_mov_to_lea): Renamed to ...
(need_convert_load): This.
(elf_x86_64_check_relocs): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX. Replace need_convert_mov_to_lea with
need_convert_load.
(elf_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(elf_x86_64_size_dynamic_sections): Likewise.
(elf_x86_64_relocate_section): Likewise.
(elf_x86_64_convert_mov_to_lea): Renamed to ...
(elf_x86_64_convert_load): This. Replace need_convert_mov_to_lea
with need_convert_load. Support R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX transformations.
* reloc.c (BFD_RELOC_X86_64_GOTPCRELX): New.
(BFD_RELOC_X86_64_REX_GOTPCRELX): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_GOTPCRELX and BFD_RELOC_X86_64_REX_GOTPCRELX.
(tc_gen_reloc): Likewise.
(i386_validate_fix): Generate BFD_RELOC_X86_64_GOTPCRELX or
BFD_RELOC_X86_64_REX_GOTPCRELX if fx_tcbit2 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Also return
true for BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
gas/testsuite/
* gas/i386/i386.exp: Run x86-64-gotpcrel.
* gas/i386/x86-64-gotpcrel.d: New file.
* gas/i386/x86-64-gotpcrel.s: Likewise.
* gas/i386/ilp32/x86-64-gotpcrel.d: Likewise.
* gas/i386/x86-64-localpic.d: Replace R_X86_64_GOTPCREL with
R_X86_64_REX_GOTPCRELX.
* gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/elf/
* x86-64.h (R_X86_64_GOTPCRELX): New.
(R_X86_64_REX_GOTPCRELX): Likewise.
ld/testsuite/
* ld-ifunc/ifunc-5r-local-x86-64.d: Replace R_X86_64_GOTPCREL
with R_X86_64_REX_GOTPCRELX.
* ld-x86-64/plt-main1.rd: Likewise.
* ld-x86-64/plt-main3.rd: Likewise.
* ld-x86-64/plt-main4.rd: Likewise.
* ld-x86-64/gotpcrel1.dd: New file.
* ld-x86-64/gotpcrel1.out: Likewise.
* ld-x86-64/gotpcrel1a.S: Likewise.
* ld-x86-64/gotpcrel1b.c: Likewise.
* ld-x86-64/gotpcrel1c.c: Likewise.
* ld-x86-64/gotpcrel1d.S: Likewise.
* ld-x86-64/load1.s: Likewise.
* ld-x86-64/load1a.d: Likewise.
* ld-x86-64/load1b.d: Likewise.
* ld-x86-64/load1c.d: Likewise.
* ld-x86-64/load1d.d: Likewise.
* ld-x86-64/x86-64.exp: Run load1a, load1b, load1c and load1d
tests. Run gotpcrel1 test.
2015-10-22 19:49:20 +08:00
|
|
|
#define TC_FORCE_RELOCATION_LOCAL(FIX) \
|
2017-05-16 07:13:24 +08:00
|
|
|
(GENERIC_FORCE_RELOCATION_LOCAL (FIX) \
|
Add R_X86_64_[REX_]GOTPCRELX support to gas and ld
This patch adds support for the R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX relocations proposed in
https://groups.google.com/forum/#!topic/x86-64-abi/n9AWHogmVY0
to gas and ld. It updates gas to generate R_X86_64_GOTPCRELX,
R_X86_64_REX_GOTPCRELX if there is a REX prefix, relocation for memory
operand, foo@GOTPCREL(%rip). With the locally defined symbol, foo, we
convert
mov foo@GOTPCREL(%rip), %reg
to
lea foo(%rip), %reg
and convert
call/jmp *foo@GOTPCREL(%rip)
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg, foo@GOTPCREL(%rip)
to
test $foo, %reg
and convert
binop foo@GOTPCREL(%rip), %reg
to
binop $foo, %reg
where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions.
bfd/
* elf64-x86-64.c: Include opcode/i386.h.
(x86_64_elf_howto_table): Add R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(R_X86_64_standard): Replace R_X86_64_PLT32_BND with
R_X86_64_REX_GOTPCRELX.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
(need_convert_mov_to_lea): Renamed to ...
(need_convert_load): This.
(elf_x86_64_check_relocs): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX. Replace need_convert_mov_to_lea with
need_convert_load.
(elf_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(elf_x86_64_size_dynamic_sections): Likewise.
(elf_x86_64_relocate_section): Likewise.
(elf_x86_64_convert_mov_to_lea): Renamed to ...
(elf_x86_64_convert_load): This. Replace need_convert_mov_to_lea
with need_convert_load. Support R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX transformations.
* reloc.c (BFD_RELOC_X86_64_GOTPCRELX): New.
(BFD_RELOC_X86_64_REX_GOTPCRELX): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_GOTPCRELX and BFD_RELOC_X86_64_REX_GOTPCRELX.
(tc_gen_reloc): Likewise.
(i386_validate_fix): Generate BFD_RELOC_X86_64_GOTPCRELX or
BFD_RELOC_X86_64_REX_GOTPCRELX if fx_tcbit2 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Also return
true for BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
gas/testsuite/
* gas/i386/i386.exp: Run x86-64-gotpcrel.
* gas/i386/x86-64-gotpcrel.d: New file.
* gas/i386/x86-64-gotpcrel.s: Likewise.
* gas/i386/ilp32/x86-64-gotpcrel.d: Likewise.
* gas/i386/x86-64-localpic.d: Replace R_X86_64_GOTPCREL with
R_X86_64_REX_GOTPCRELX.
* gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/elf/
* x86-64.h (R_X86_64_GOTPCRELX): New.
(R_X86_64_REX_GOTPCRELX): Likewise.
ld/testsuite/
* ld-ifunc/ifunc-5r-local-x86-64.d: Replace R_X86_64_GOTPCREL
with R_X86_64_REX_GOTPCRELX.
* ld-x86-64/plt-main1.rd: Likewise.
* ld-x86-64/plt-main3.rd: Likewise.
* ld-x86-64/plt-main4.rd: Likewise.
* ld-x86-64/gotpcrel1.dd: New file.
* ld-x86-64/gotpcrel1.out: Likewise.
* ld-x86-64/gotpcrel1a.S: Likewise.
* ld-x86-64/gotpcrel1b.c: Likewise.
* ld-x86-64/gotpcrel1c.c: Likewise.
* ld-x86-64/gotpcrel1d.S: Likewise.
* ld-x86-64/load1.s: Likewise.
* ld-x86-64/load1a.d: Likewise.
* ld-x86-64/load1b.d: Likewise.
* ld-x86-64/load1c.d: Likewise.
* ld-x86-64/load1d.d: Likewise.
* ld-x86-64/x86-64.exp: Run load1a, load1b, load1c and load1d
tests. Run gotpcrel1 test.
2015-10-22 19:49:20 +08:00
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_386_PLT32 \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \
|
2018-12-09 23:22:14 +08:00
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \
|
Add R_X86_64_[REX_]GOTPCRELX support to gas and ld
This patch adds support for the R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX relocations proposed in
https://groups.google.com/forum/#!topic/x86-64-abi/n9AWHogmVY0
to gas and ld. It updates gas to generate R_X86_64_GOTPCRELX,
R_X86_64_REX_GOTPCRELX if there is a REX prefix, relocation for memory
operand, foo@GOTPCREL(%rip). With the locally defined symbol, foo, we
convert
mov foo@GOTPCREL(%rip), %reg
to
lea foo(%rip), %reg
and convert
call/jmp *foo@GOTPCREL(%rip)
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg, foo@GOTPCREL(%rip)
to
test $foo, %reg
and convert
binop foo@GOTPCREL(%rip), %reg
to
binop $foo, %reg
where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions.
bfd/
* elf64-x86-64.c: Include opcode/i386.h.
(x86_64_elf_howto_table): Add R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(R_X86_64_standard): Replace R_X86_64_PLT32_BND with
R_X86_64_REX_GOTPCRELX.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
(need_convert_mov_to_lea): Renamed to ...
(need_convert_load): This.
(elf_x86_64_check_relocs): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX. Replace need_convert_mov_to_lea with
need_convert_load.
(elf_x86_64_gc_sweep_hook): Handle R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX.
(elf_x86_64_size_dynamic_sections): Likewise.
(elf_x86_64_relocate_section): Likewise.
(elf_x86_64_convert_mov_to_lea): Renamed to ...
(elf_x86_64_convert_load): This. Replace need_convert_mov_to_lea
with need_convert_load. Support R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX transformations.
* reloc.c (BFD_RELOC_X86_64_GOTPCRELX): New.
(BFD_RELOC_X86_64_REX_GOTPCRELX): Likewise.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_GOTPCRELX and BFD_RELOC_X86_64_REX_GOTPCRELX.
(tc_gen_reloc): Likewise.
(i386_validate_fix): Generate BFD_RELOC_X86_64_GOTPCRELX or
BFD_RELOC_X86_64_REX_GOTPCRELX if fx_tcbit2 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Also return
true for BFD_RELOC_X86_64_GOTPCRELX and
BFD_RELOC_X86_64_REX_GOTPCRELX.
gas/testsuite/
* gas/i386/i386.exp: Run x86-64-gotpcrel.
* gas/i386/x86-64-gotpcrel.d: New file.
* gas/i386/x86-64-gotpcrel.s: Likewise.
* gas/i386/ilp32/x86-64-gotpcrel.d: Likewise.
* gas/i386/x86-64-localpic.d: Replace R_X86_64_GOTPCREL with
R_X86_64_REX_GOTPCRELX.
* gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/elf/
* x86-64.h (R_X86_64_GOTPCRELX): New.
(R_X86_64_REX_GOTPCRELX): Likewise.
ld/testsuite/
* ld-ifunc/ifunc-5r-local-x86-64.d: Replace R_X86_64_GOTPCREL
with R_X86_64_REX_GOTPCRELX.
* ld-x86-64/plt-main1.rd: Likewise.
* ld-x86-64/plt-main3.rd: Likewise.
* ld-x86-64/plt-main4.rd: Likewise.
* ld-x86-64/gotpcrel1.dd: New file.
* ld-x86-64/gotpcrel1.out: Likewise.
* ld-x86-64/gotpcrel1a.S: Likewise.
* ld-x86-64/gotpcrel1b.c: Likewise.
* ld-x86-64/gotpcrel1c.c: Likewise.
* ld-x86-64/gotpcrel1d.S: Likewise.
* ld-x86-64/load1.s: Likewise.
* ld-x86-64/load1a.d: Likewise.
* ld-x86-64/load1b.d: Likewise.
* ld-x86-64/load1c.d: Likewise.
* ld-x86-64/load1d.d: Likewise.
* ld-x86-64/x86-64.exp: Run load1a, load1b, load1c and load1d
tests. Run gotpcrel1 test.
2015-10-22 19:49:20 +08:00
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \
|
x86-64: Add R_X86_64_CODE_4_GOTPCRELX
For
mov name@GOTPCREL(%rip), %reg
test %reg, name@GOTPCREL(%rip)
binop name@GOTPCREL(%rip), %reg
where binop is one of adc, add, add, cmp, or, sbb, sub, xor instructions,
add
# define R_X86_64_CODE_4_GOTPCRELX 43
if the instruction starts at 4 bytes before the relocation offset. It
similar to R_X86_64_GOTPCRELX. Linker can treat R_X86_64_CODE_4_GOTPCRELX
as R_X86_64_GOTPCREL or convert the above instructions to
lea name(%rip), %reg
mov $name, %reg
test $name, %reg
binop $name, %reg
if the instruction is encoded with the REX2 prefix when possible.
bfd/
* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_4_GOTPCRELX.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_convert_load_reloc): Handle R_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* write.h (fix): Add fx_tcbit3. Change fx_unused to 1 bit.
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(tc_gen_reloc): Likewise.
(output_disp): Set fixP->fx_tcbit3 for REX2 prefix.
(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTPCRELX
if fixp->fx_tcbit3 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(TC_FORCE_RELOCATION_ABS): Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.s: Add tests for
R_X86_64_CODE_4_GOTPCRELX.
* testsuite/gas/i386/x86-64-localpic.s: Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.d: Updated.
* testsuite/gas/i386/x86-64-localpic.d: Likewise.
* testsuite/gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/
* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_4_GOTPCRELX.
ld/
* testsuite/ld-x86-64/apx-load1.s: New file.
* testsuite/ld-x86-64/apx-load1a.d: Likewise.
* testsuite/ld-x86-64/apx-load1b.d: Likewise.
* testsuite/ld-x86-64/apx-load1c.d: Likewise.
* testsuite/ld-x86-64/apx-load1d.d: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run apx-load1a, apx-load1b,
apx-load1c and apx-load1d.
2023-06-09 01:01:03 +08:00
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
|
2002-08-09 20:37:41 +08:00
|
|
|
|
2020-04-01 20:40:45 +08:00
|
|
|
#define TC_FORCE_RELOCATION_ABS(FIX) \
|
|
|
|
(TC_FORCE_RELOCATION (FIX) \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_386_GOT32 \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_386_GOT32X \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \
|
x86-64: Add R_X86_64_CODE_4_GOTPCRELX
For
mov name@GOTPCREL(%rip), %reg
test %reg, name@GOTPCREL(%rip)
binop name@GOTPCREL(%rip), %reg
where binop is one of adc, add, add, cmp, or, sbb, sub, xor instructions,
add
# define R_X86_64_CODE_4_GOTPCRELX 43
if the instruction starts at 4 bytes before the relocation offset. It
similar to R_X86_64_GOTPCRELX. Linker can treat R_X86_64_CODE_4_GOTPCRELX
as R_X86_64_GOTPCREL or convert the above instructions to
lea name(%rip), %reg
mov $name, %reg
test $name, %reg
binop $name, %reg
if the instruction is encoded with the REX2 prefix when possible.
bfd/
* elf64-x86-64.c (x86_64_elf_howto_table): Add
R_X86_64_CODE_4_GOTPCRELX.
(R_X86_64_standard): Updated.
(x86_64_reloc_map): Add BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_convert_load_reloc): Handle R_X86_64_CODE_4_GOTPCRELX.
(elf_x86_64_scan_relocs): Likewise.
(elf_x86_64_relocate_section): Likewise.
* reloc.c (bfd_reloc_code_real): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
* bfd-in2.h: Regenerated.
* libbfd.h: Likewise.
gas/
* write.h (fix): Add fx_tcbit3. Change fx_unused to 1 bit.
* config/tc-i386.c (tc_i386_fix_adjustable): Handle
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(tc_gen_reloc): Likewise.
(output_disp): Set fixP->fx_tcbit3 for REX2 prefix.
(i386_validate_fix): Generate BFD_RELOC_X86_64_CODE_4_GOTPCRELX
if fixp->fx_tcbit3 is set.
* config/tc-i386.h (TC_FORCE_RELOCATION_LOCAL): Add
BFD_RELOC_X86_64_CODE_4_GOTPCRELX.
(TC_FORCE_RELOCATION_ABS): Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.s: Add tests for
R_X86_64_CODE_4_GOTPCRELX.
* testsuite/gas/i386/x86-64-localpic.s: Likewise.
* testsuite/gas/i386/x86-64-gotpcrel.d: Updated.
* testsuite/gas/i386/x86-64-localpic.d: Likewise.
* testsuite/gas/i386/ilp32/x86-64-localpic.d: Likewise.
include/
* elf/x86-64.h (elf_x86_64_reloc_type): Add
R_X86_64_CODE_4_GOTPCRELX.
ld/
* testsuite/ld-x86-64/apx-load1.s: New file.
* testsuite/ld-x86-64/apx-load1a.d: Likewise.
* testsuite/ld-x86-64/apx-load1b.d: Likewise.
* testsuite/ld-x86-64/apx-load1c.d: Likewise.
* testsuite/ld-x86-64/apx-load1d.d: Likewise.
* testsuite/ld-x86-64/x86-64.exp: Run apx-load1a, apx-load1b,
apx-load1c and apx-load1d.
2023-06-09 01:01:03 +08:00
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \
|
|
|
|
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_CODE_4_GOTPCRELX)
|
2020-04-01 20:40:45 +08:00
|
|
|
|
2024-07-19 17:44:07 +08:00
|
|
|
extern void i386_start_line (void);
|
|
|
|
#define md_start_line_hook i386_start_line
|
|
|
|
|
|
|
|
extern bool i386_check_label (void);
|
|
|
|
#define TC_START_LABEL(STR, NUL_CHAR, NEXT_CHAR) \
|
|
|
|
(NEXT_CHAR == ':' && i386_check_label ())
|
|
|
|
|
|
|
|
extern int i386_unrecognized_line (int);
|
|
|
|
#define tc_unrecognized_line i386_unrecognized_line
|
|
|
|
|
2005-10-26 20:29:44 +08:00
|
|
|
extern int i386_parse_name (char *, expressionS *, char *);
|
|
|
|
#define md_parse_name(s, e, m, c) i386_parse_name (s, e, c)
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2009-04-20 14:31:50 +08:00
|
|
|
extern operatorT i386_operator (const char *name, unsigned int operands, char *);
|
|
|
|
#define md_operator i386_operator
|
|
|
|
|
|
|
|
extern int i386_need_index_operator (void);
|
|
|
|
#define md_need_index_operator i386_need_index_operator
|
|
|
|
|
2023-05-19 15:18:09 +08:00
|
|
|
#ifdef BFD64
|
|
|
|
extern bool i386_record_operator
|
|
|
|
(operatorT, const expressionS *, const expressionS *);
|
|
|
|
#define md_optimize_expr(l, o, r) i386_record_operator (o, l, r)
|
|
|
|
#endif
|
|
|
|
|
2007-09-26 16:34:24 +08:00
|
|
|
#define md_register_arithmetic 0
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
extern const struct relax_type md_relax_table[];
|
|
|
|
#define TC_GENERIC_RELAX_TABLE md_relax_table
|
|
|
|
|
2003-06-10 14:46:34 +08:00
|
|
|
extern int optimize_align_code;
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
#define md_do_align(n, fill, len, max, around) \
|
2003-06-10 14:46:34 +08:00
|
|
|
if ((n) \
|
|
|
|
&& !need_pass_2 \
|
|
|
|
&& optimize_align_code \
|
|
|
|
&& (!(fill) \
|
|
|
|
|| ((char)*(fill) == (char)0x90 && (len) == 1)) \
|
1999-06-13 00:49:51 +08:00
|
|
|
&& subseg_text_p (now_seg)) \
|
1999-05-03 15:29:11 +08:00
|
|
|
{ \
|
2000-12-28 18:07:56 +08:00
|
|
|
frag_align_code ((n), (max)); \
|
1999-05-03 15:29:11 +08:00
|
|
|
goto around; \
|
|
|
|
}
|
|
|
|
|
2022-06-03 21:10:21 +08:00
|
|
|
#define MAX_MEM_FOR_RS_ALIGN_CODE \
|
|
|
|
(alignment ? ((size_t) 1 << alignment) - 1 : (size_t) 1)
|
1999-05-03 15:29:11 +08:00
|
|
|
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
extern void i386_cons_align (int);
|
|
|
|
#define md_cons_align(nbytes) i386_cons_align (nbytes)
|
|
|
|
|
2024-10-04 15:42:13 +08:00
|
|
|
#ifndef OBJ_AOUT
|
2023-11-17 18:20:49 +08:00
|
|
|
#define md_section_align(seg, value) ((void)(seg), (value))
|
|
|
|
#endif
|
|
|
|
|
2007-01-04 06:36:19 +08:00
|
|
|
void i386_print_statistics (FILE *);
|
1999-05-03 15:29:11 +08:00
|
|
|
#define tc_print_statistics i386_print_statistics
|
|
|
|
|
2022-07-07 20:36:55 +08:00
|
|
|
void i386_md_end (void);
|
|
|
|
#define md_end i386_md_end
|
|
|
|
|
2012-03-14 00:59:57 +08:00
|
|
|
extern unsigned int i386_frag_max_var (fragS *);
|
|
|
|
#define md_frag_max_var i386_frag_max_var
|
|
|
|
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
extern long i386_generic_table_relax_frag (segT, fragS *, long);
|
|
|
|
#define md_generic_table_relax_frag(segment, fragP, stretch) \
|
|
|
|
i386_generic_table_relax_frag (segment, fragP, stretch)
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
#define md_number_to_chars number_to_chars_littleendian
|
|
|
|
|
2008-10-12 20:37:09 +08:00
|
|
|
enum processor_type
|
|
|
|
{
|
|
|
|
PROCESSOR_UNKNOWN,
|
2022-07-05 14:40:39 +08:00
|
|
|
PROCESSOR_GENERIC32,
|
|
|
|
PROCESSOR_GENERIC64,
|
2008-10-12 20:37:09 +08:00
|
|
|
PROCESSOR_I386,
|
|
|
|
PROCESSOR_I486,
|
|
|
|
PROCESSOR_PENTIUM,
|
2023-10-23 16:33:02 +08:00
|
|
|
PROCESSOR_I686,
|
2008-10-12 20:37:09 +08:00
|
|
|
PROCESSOR_PENTIUMPRO,
|
|
|
|
PROCESSOR_PENTIUM4,
|
|
|
|
PROCESSOR_NOCONA,
|
|
|
|
PROCESSOR_CORE,
|
|
|
|
PROCESSOR_CORE2,
|
gas/
2009-01-10 H.J. Lu <hongjiu.lu@intel.com>
* gas/config/tc-i386.c (cpu_arch): Add corei7, .clflush and
.syscall.
(i386_align_code): Handle PROCESSOR_COREI7.
(md_show_usage): Add corei7, clflush and syscall.
(i386_target_format): Replace cpup4 with cpuclflush.
* gas/config/tc-i386.h (processor_type): Add PROCESSOR_COREI7.
* doc/c-i386.texi: Document corei7, clflush and syscall.
gas/testsuite/
2009-01-10 H.J. Lu <hongjiu.lu@intel.com>
* gas/i386/arch-10.s: Add clflush and syscall.
* gas/i386/x86-64-arch-2.s: Likewise.
* gas/i386/arch-10.d: Updated.
* gas/i386/arch-10-1.l: Likewise.
* gas/i386/arch-10-2.l: Likewise.
* gas/i386/arch-10-3.l: Likewise.
* gas/i386/arch-10-4.l: Likewise.
* gas/i386/x86-64-arch-2.d: Likewise.
opcodes/
2009-01-10 H.J. Lu <hongjiu.lu@intel.com>
* i386-gen.c (cpu_flag_init): Replace CpuP4 and CpuK6 with
CpuClflush and CpuSYSCALL, respectively. Remove CpuK8. Add
CPU_COREI7_FLAGS, CPU_CLFLUSH_FLAGS and CPU_SYSCALL_FLAGS.
(cpu_flags): Remove CpuP4, CpuK6 and CpuK8. Add CpuClflush
and CpuSYSCALL.
(lineno): Removed.
(set_bitfield): Take an argument, lineno. Don't report lineno
on error if it is -1.
(process_i386_cpu_flag): Take an argument, lineno.
(process_i386_opcode_modifier): Likewise.
(process_i386_operand_type): Likewise.
(output_i386_opcode): Likewise.
(opcode_hash_entry): Add lineno.
(process_i386_opcodes): Updated.
(process_i386_registers): Likewise.
(process_i386_initializers): Likewise.
* i386-opc.h (CpuP4): Removed.
(CpuK6): Likewise.
(CpuK8): Likewise.
(CpuClflush): New.
(CpuSYSCALL): Likewise.
(CpuMMX): Updated.
(i386_cpu_flags): Remove cpup4, cpuk6 and cpuk8. Add
cpuclflush and cpusyscall.
* i386-opc.tbl: Update movnti, clflush, lfence, mfence, pause,
syscall and sysret.
* i386-init.h: Regenerated.
* i386-tbl.h: Likewise.
2009-01-11 01:25:52 +08:00
|
|
|
PROCESSOR_COREI7,
|
2015-05-12 02:11:19 +08:00
|
|
|
PROCESSOR_IAMCU,
|
2008-10-12 20:37:09 +08:00
|
|
|
PROCESSOR_K6,
|
|
|
|
PROCESSOR_ATHLON,
|
|
|
|
PROCESSOR_K8,
|
2010-01-07 06:52:47 +08:00
|
|
|
PROCESSOR_AMDFAM10,
|
2012-08-18 01:12:36 +08:00
|
|
|
PROCESSOR_BD,
|
2015-03-18 00:19:15 +08:00
|
|
|
PROCESSOR_ZNVER,
|
2022-07-05 14:40:39 +08:00
|
|
|
PROCESSOR_BT,
|
|
|
|
/* Keep this last. */
|
|
|
|
PROCESSOR_NONE
|
2008-10-12 20:37:09 +08:00
|
|
|
};
|
|
|
|
|
2023-10-23 16:32:32 +08:00
|
|
|
extern i386_cpu_flags cpu_arch_flags;
|
2008-10-12 20:37:09 +08:00
|
|
|
extern enum processor_type cpu_arch_tune;
|
|
|
|
extern enum processor_type cpu_arch_isa;
|
|
|
|
extern i386_cpu_flags cpu_arch_isa_flags;
|
|
|
|
|
2023-10-23 16:28:44 +08:00
|
|
|
/* We support four different modes. I386_FLAG_CODE variable is used to
|
|
|
|
distinguish three of these. */
|
|
|
|
|
|
|
|
extern enum i386_flag_code {
|
|
|
|
CODE_32BIT,
|
|
|
|
CODE_16BIT,
|
|
|
|
CODE_64BIT
|
|
|
|
} i386_flag_code;
|
|
|
|
|
2023-12-01 15:27:22 +08:00
|
|
|
struct i386_segment_info {
|
|
|
|
/* Type of previous "instruction", e.g. .byte or stand-alone prefix. */
|
|
|
|
struct last_insn {
|
|
|
|
const char *file;
|
|
|
|
const char *name;
|
|
|
|
unsigned int line;
|
|
|
|
enum last_insn_kind
|
|
|
|
{
|
|
|
|
last_insn_other = 0,
|
|
|
|
last_insn_directive,
|
|
|
|
last_insn_prefix
|
|
|
|
} kind;
|
|
|
|
} last_insn;
|
2023-12-15 19:42:43 +08:00
|
|
|
subsegT subseg;
|
|
|
|
struct i386_segment_info *next;
|
2023-12-01 15:27:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define TC_SEGMENT_INFO_TYPE struct i386_segment_info
|
|
|
|
|
2008-10-12 20:37:09 +08:00
|
|
|
struct i386_tc_frag_data
|
|
|
|
{
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
union
|
|
|
|
{
|
|
|
|
fragS *padding_fragP;
|
|
|
|
fragS *branch_fragP;
|
|
|
|
} u;
|
|
|
|
addressT padding_address;
|
2008-10-12 20:37:09 +08:00
|
|
|
enum processor_type isa;
|
|
|
|
enum processor_type tune;
|
2023-10-23 16:28:44 +08:00
|
|
|
enum i386_flag_code code;
|
2019-02-10 20:34:10 +08:00
|
|
|
unsigned int max_bytes;
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
unsigned char length;
|
|
|
|
unsigned char last_length;
|
|
|
|
unsigned char max_prefix_length;
|
|
|
|
unsigned char prefix_length;
|
|
|
|
unsigned char default_prefix;
|
|
|
|
unsigned char cmp_size;
|
x86: Improve -malign-branch
According to intel SDM manual, not all compare flag-modifying instructions
are marcro-fusible with subsequent jcc instructions. For those non-fusible
instructions, -malign-branch doesn't need to align them, only jcc itself
needs to be aligned.
Here are 2 restrictions which separate macro-fusible instruction from not
Restriction 1:
If TEST/AND/CMP/ADD/SUB/INC/DEC is one of the following format:
cmp m, imm
add m, imm
sub m, imm
test m, imm
and m, imm
inc m
dec m
it is unfusible with any jcc instruction.
Restriction 2:
/* Table 3-2. Macro-Fusible Instructions in Haswell Microarchitecture
Note it also works for Skylake and Cascadelake.
---------------------------------------------------------------------
| JCC | ADD/SUB/CMP | INC/DEC | TEST/AND |
| ------ | ----------- | ------- | -------- |
| Jo | N | N | Y |
| Jno | N | N | Y |
| Jc/Jb | Y | N | Y |
| Jae/Jnb | Y | N | Y |
| Je/Jz | Y | Y | Y |
| Jne/Jnz | Y | Y | Y |
| Jna/Jbe | Y | N | Y |
| Ja/Jnbe | Y | N | Y |
| Js | N | N | Y |
| Jns | N | N | Y |
| Jp/Jpe | N | N | Y |
| Jnp/Jpo | N | N | Y |
| Jl/Jnge | Y | Y | Y |
| Jge/Jnl | Y | Y | Y |
| Jle/Jng | Y | Y | Y |
| Jg/Jnle | Y | Y | Y |
Update maybe_fused_with_jcc_p to check if operands of CMP like instructions
can be fused with condition jump.
* gas/config/tc-i386.h (i386_tc_frag_data): Add member mf_type.
(TC_FRAG_INIT): Init mf_type.
* gas/config/tc-i386.c (enum mf_jcc_kind): New enum.
(enum mf_cmp_kind): Ditto.
(maybe_fused_with_jcc_p): Add argument mf_cmp_p to get
mf_type of corresponding instructons, exclude unfusible
instructions.
(add_fused_jcc_padding_frag_p): Likewise.
(add_branch_padding_frag_p): Likewise.
(output_insn): Record mf_type for corresponding instructions.
(i386_macro_fusible_p): New function.
(i386_next_fusible_jcc_frag): Rename from i386_next_jcc_frag,
add argument cmp_fragP to return next fusible jcc frag only.
(i386_classify_machine_dependant_frag): Seperate macro-fusible
instructions from condition jump.
* gas/testsuite/gas/i386/align-branch-9.s: New file.
* gas/testsuite/gas/i386/align-branch-9.d: Ditto.
* gas/testsuite/gas/i386/x86-64-align-branch-9.s: Ditto.
* gas/testsuite/gas/i386/x86-64-align-branch-9.d: Ditto.
* gas/testsuite/gas/i386/i386.exp: Run new tests.
2020-03-03 22:21:37 +08:00
|
|
|
unsigned int mf_type : 3;
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
unsigned int classified : 1;
|
|
|
|
unsigned int branch_type : 3;
|
2023-10-23 16:32:32 +08:00
|
|
|
unsigned int cpunop : 1;
|
2023-10-23 16:33:25 +08:00
|
|
|
unsigned int isanop : 1;
|
2023-12-01 15:29:11 +08:00
|
|
|
unsigned int last_insn_normal : 1;
|
2008-10-12 20:37:09 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
/* We need to emit the right NOP pattern in .align frags. This is
|
|
|
|
done after the text-to-bits assembly pass, so we need to mark it with
|
|
|
|
the isa/tune settings at the time the .align was assembled. */
|
|
|
|
#define TC_FRAG_TYPE struct i386_tc_frag_data
|
|
|
|
|
2019-02-10 20:34:10 +08:00
|
|
|
#define TC_FRAG_INIT(FRAGP, MAX_BYTES) \
|
2008-10-12 20:37:09 +08:00
|
|
|
do \
|
|
|
|
{ \
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
(FRAGP)->tc_frag_data.u.padding_fragP = NULL; \
|
|
|
|
(FRAGP)->tc_frag_data.padding_address = 0; \
|
2008-10-12 20:37:09 +08:00
|
|
|
(FRAGP)->tc_frag_data.isa = cpu_arch_isa; \
|
|
|
|
(FRAGP)->tc_frag_data.tune = cpu_arch_tune; \
|
2023-10-23 16:32:32 +08:00
|
|
|
(FRAGP)->tc_frag_data.cpunop = cpu_arch_flags.bitfield.cpunop; \
|
2023-10-23 16:33:25 +08:00
|
|
|
(FRAGP)->tc_frag_data.isanop = cpu_arch_isa_flags.bitfield.cpunop; \
|
2023-10-23 16:28:44 +08:00
|
|
|
(FRAGP)->tc_frag_data.code = i386_flag_code; \
|
2019-02-10 20:34:10 +08:00
|
|
|
(FRAGP)->tc_frag_data.max_bytes = (MAX_BYTES); \
|
i386: Align branches within a fixed boundary
Add 3 command-line options to align branches within a fixed boundary
with segment prefixes or NOPs:
1. -malign-branch-boundary=NUM aligns branches within NUM byte boundary.
2. -malign-branch=TYPE[+TYPE...] specifies types of branches to align.
The supported branches are:
a. Conditional jump.
b. Fused conditional jump.
c. Unconditional jump.
d. Call.
e. Ret.
f. Indirect jump and call.
3. -malign-branch-prefix-size=NUM aligns branches with NUM segment
prefixes per instruction.
3 new rs_machine_dependent frag types are added:
1. BRANCH_PADDING. The variable size frag to insert NOP before branch.
2. BRANCH_PREFIX. The variable size frag to insert segment prefixes to
an instruction. The choices of prefixes are:
a. Use the existing segment prefix if there is one.
b. Use CS segment prefix in 64-bit mode.
c. In 32-bit mode, use SS segment prefix with ESP/EBP base register
and use DS segment prefix without ESP/EBP base register.
3. FUSED_JCC_PADDING. The variable size frag to insert NOP before fused
conditional jump.
The new rs_machine_dependent frags aren't inserted if the previous item
is a prefix or a constant directive, which may be used to hardcode an
instruction, since there is no clear instruction boundary. Segment
prefixes and NOP padding are disabled before relaxable TLS relocations
and tls_get_addr calls to keep TLS instruction sequence unchanged.
md_estimate_size_before_relax() and i386_generic_table_relax_frag() are
used to handled BRANCH_PADDING, BRANCH_PREFIX and FUSED_JCC_PADDING frags.
i386_generic_table_relax_frag() grows or shrinks sizes of segment prefix
and NOP to align the next branch frag:
1. First try to add segment prefixes to instructions before a branch.
2. If there is no sufficient room to add segment prefixes, NOP will be
inserted before a branch.
* config/tc-i386.c (_i386_insn): Add has_gotpc_tls_reloc.
(tls_get_addr): New.
(last_insn): New.
(align_branch_power): New.
(align_branch_kind): New.
(align_branch_bit): New.
(align_branch): New.
(MAX_FUSED_JCC_PADDING_SIZE): New.
(align_branch_prefix_size): New.
(BRANCH_PADDING): New.
(BRANCH_PREFIX): New.
(FUSED_JCC_PADDING): New.
(i386_generate_nops): Support BRANCH_PADDING and FUSED_JCC_PADDING.
(md_begin): Abort if align_branch_prefix_size <
MAX_FUSED_JCC_PADDING_SIZE.
(md_assemble): Set last_insn.
(maybe_fused_with_jcc_p): New.
(add_fused_jcc_padding_frag_p): New.
(add_branch_prefix_frag_p): New.
(add_branch_padding_frag_p): New.
(output_insn): Generate a BRANCH_PADDING, FUSED_JCC_PADDING or
BRANCH_PREFIX frag and terminate each frag to align branches.
(output_disp): Set i.has_gotpc_tls_reloc to TRUE for GOTPC and
relaxable TLS relocations.
(output_imm): Likewise.
(i386_next_non_empty_frag): New.
(i386_next_jcc_frag): New.
(i386_classify_machine_dependent_frag): New.
(i386_branch_padding_size): New.
(i386_generic_table_relax_frag): New.
(md_estimate_size_before_relax): Handle COND_JUMP_PADDING,
FUSED_JCC_PADDING and COND_JUMP_PREFIX frags.
(md_convert_frag): Handle BRANCH_PADDING, BRANCH_PREFIX and
FUSED_JCC_PADDING frags.
(OPTION_MALIGN_BRANCH_BOUNDARY): New.
(OPTION_MALIGN_BRANCH_PREFIX_SIZE): New.
(OPTION_MALIGN_BRANCH): New.
(md_longopts): Add -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_parse_option): Handle -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(md_show_usage): Display -malign-branch-boundary=,
-malign-branch-prefix-size= and -malign-branch=.
(i386_target_format): Set tls_get_addr.
(i386_cons_align): New.
* config/tc-i386.h (i386_cons_align): New.
(md_cons_align): New.
(i386_generic_table_relax_frag): New.
(md_generic_table_relax_frag): New.
(i386_tc_frag_data): Add u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
(TC_FRAG_INIT): Initialize u, padding_address, length,
max_prefix_length, prefix_length, default_prefix, cmp_size,
classified and branch_type.
* doc/c-i386.texi: Document -malign-branch-boundary=,
-malign-branch= and -malign-branch-prefix-size=.
2019-12-13 03:56:06 +08:00
|
|
|
(FRAGP)->tc_frag_data.length = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.last_length = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.max_prefix_length = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.prefix_length = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.default_prefix = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.cmp_size = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.classified = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.branch_type = 0; \
|
2023-12-01 15:29:11 +08:00
|
|
|
(FRAGP)->tc_frag_data.mf_type = 0; \
|
|
|
|
(FRAGP)->tc_frag_data.last_insn_normal \
|
|
|
|
= (seg_info(now_seg)->tc_segment_info_data.last_insn.kind \
|
|
|
|
== last_insn_other); \
|
2008-10-12 20:37:09 +08:00
|
|
|
} \
|
|
|
|
while (0)
|
|
|
|
|
2007-03-09 20:35:37 +08:00
|
|
|
#define WORKING_DOT_WORD 1
|
|
|
|
|
Add .nop assembler directive
Implement the '.nop SIZE[, CONTROL]' assembler directive, which emits
SIZE bytes filled with no-op instructions. SIZE is absolute expression.
The optional CONTROL byte controls how no-op instructions should be
generated. If the comma and @var{control} are omitted, CONTROL is
assumed to be zero.
For Intel 80386 and AMD x86-64 targets, CONTROL byte specifies the size
limit of a single no-op instruction. The valid values of CONTROL byte
are between 0 and 8 for 16-bit mode, between 0 and 10 for 32-bit mode,
between 0 and 11 for 64-bit mode. When 0 is used, the no-op size limit
is set to the maximum supported size.
2 new relax states, rs_space_nop and rs_fill_nop, are added to enum
_relax_state, which are similar to rs_space and rs_fill, respectively,
but they fill with no-op instructions, instead of a single byte. A
target backend must override the default md_generate_nops to generate
proper no-op instructions. Otherwise, an error of unimplemented .nop
directive will be issued whenever .nop directive is used.
* NEWS: Mention .nop directive.
* as.h (_relax_state): Add rs_space_nop and rs_fill_nop.
* read.c (potable): Add .nop.
(s_nop): New function.
* read.h (s_nop): New prototype.
* write.c (cvt_frag_to_fill): Handle rs_space_nop and
rs_fill_nop.
(md_generate_nops): New function.
(relax_segment): Likewise.
(write_contents): Use md_generate_nops for rs_fill_nop.
* config/tc-i386.c (alt64_11): New.
(alt64_patt): Likewise.
(md_convert_frag): Handle rs_space_nop.
(i386_output_nops): New function.
(i386_generate_nops): Likewise.
(i386_align_code): Call i386_output_nops.
* config/tc-i386.h (i386_generate_nops): New.
(md_generate_nops): Likewise.
* doc/as.texinfo: Document .nop directive.
* testsuite/gas/i386/i386.exp: Run .nop directive tests.
* testsuite/gas/i386/nop-1.d: New file.
* testsuite/gas/i386/nop-1.s: Likewise.
* testsuite/gas/i386/nop-2.d: Likewise.
* testsuite/gas/i386/nop-2.s: Likewise.
* testsuite/gas/i386/nop-3.d: Likewise.
* testsuite/gas/i386/nop-3.s: Likewise.
* testsuite/gas/i386/nop-4.d: Likewise.
* testsuite/gas/i386/nop-4.s: Likewise.
* testsuite/gas/i386/nop-5.d: Likewise.
* testsuite/gas/i386/nop-5.s: Likewise.
* testsuite/gas/i386/nop-6.d: Likewise.
* testsuite/gas/i386/nop-6.s: Likewise.
* testsuite/gas/i386/nop-bad-1.l: Likewise.
* testsuite/gas/i386/nop-bad-1.s: Likewise.
* testsuite/gas/i386/x86-64-nop-1.d: Likewise.
* testsuite/gas/i386/x86-64-nop-2.d: Likewise.
* testsuite/gas/i386/x86-64-nop-3.d: Likewise.
* testsuite/gas/i386/x86-64-nop-4.d: Likewise.
* testsuite/gas/i386/x86-64-nop-5.d: Likewise.
* testsuite/gas/i386/x86-64-nop-6.d: Likewise.
2018-02-17 21:20:42 +08:00
|
|
|
/* How to generate NOPs for .nop direct directive. */
|
|
|
|
extern void i386_generate_nops (fragS *, char *, offsetT, int);
|
|
|
|
#define md_generate_nops(frag, where, amount, control) \
|
|
|
|
i386_generate_nops ((frag), (where), (amount), (control))
|
|
|
|
|
2018-03-07 20:18:45 +08:00
|
|
|
#define HANDLE_ALIGN(fragP) \
|
|
|
|
if (fragP->fr_type == rs_align_code) \
|
|
|
|
{ \
|
|
|
|
offsetT __count = (fragP->fr_next->fr_address \
|
|
|
|
- fragP->fr_address \
|
|
|
|
- fragP->fr_fix); \
|
2019-02-10 20:34:10 +08:00
|
|
|
if (__count > 0 \
|
|
|
|
&& (unsigned int) __count <= fragP->tc_frag_data.max_bytes) \
|
2018-03-07 20:18:45 +08:00
|
|
|
md_generate_nops (fragP, fragP->fr_literal + fragP->fr_fix, \
|
|
|
|
__count, 0); \
|
|
|
|
}
|
|
|
|
|
2003-05-20 15:58:07 +08:00
|
|
|
/* We want .cfi_* pseudo-ops for generating unwind info. */
|
2003-05-28 00:52:49 +08:00
|
|
|
#define TARGET_USE_CFIPOP 1
|
2003-05-20 15:58:07 +08:00
|
|
|
|
2003-05-28 00:52:49 +08:00
|
|
|
extern unsigned int x86_dwarf2_return_column;
|
|
|
|
#define DWARF2_DEFAULT_RETURN_COLUMN x86_dwarf2_return_column
|
|
|
|
|
|
|
|
extern int x86_cie_data_alignment;
|
|
|
|
#define DWARF2_CIE_DATA_ALIGNMENT x86_cie_data_alignment
|
2003-05-20 15:58:07 +08:00
|
|
|
|
2011-08-02 07:04:23 +08:00
|
|
|
extern int x86_dwarf2_addr_size (void);
|
|
|
|
#define DWARF2_ADDR_SIZE(bfd) x86_dwarf2_addr_size ()
|
|
|
|
|
2008-02-13 18:14:40 +08:00
|
|
|
#define tc_parse_to_dw2regnum tc_x86_parse_to_dw2regnum
|
|
|
|
extern void tc_x86_parse_to_dw2regnum (expressionS *);
|
2003-05-20 15:58:07 +08:00
|
|
|
|
|
|
|
#define tc_cfi_frame_initial_instructions tc_x86_frame_initial_instructions
|
2007-01-04 06:36:19 +08:00
|
|
|
extern void tc_x86_frame_initial_instructions (void);
|
2003-05-20 15:58:07 +08:00
|
|
|
|
2024-03-01 16:25:59 +08:00
|
|
|
/* DWARF register number of the frame-pointer register in 64-bit mode. */
|
|
|
|
#define REG_FP 6
|
|
|
|
/* DWARF register number of the stack-pointer register in 64-bit mode. */
|
|
|
|
#define REG_SP 7
|
|
|
|
|
2004-10-08 21:55:11 +08:00
|
|
|
#define md_elf_section_type(str,len) i386_elf_section_type (str, len)
|
2007-01-04 06:36:19 +08:00
|
|
|
extern int i386_elf_section_type (const char *, size_t);
|
2004-10-08 21:55:11 +08:00
|
|
|
|
2023-12-15 19:42:43 +08:00
|
|
|
#define md_elf_section_change_hook i386_elf_section_change_hook
|
|
|
|
extern void i386_elf_section_change_hook (void);
|
|
|
|
|
2008-10-10 01:31:43 +08:00
|
|
|
#ifdef TE_SOLARIS
|
|
|
|
#define md_fix_up_eh_frame(sec) i386_solaris_fix_up_eh_frame (sec)
|
|
|
|
extern void i386_solaris_fix_up_eh_frame (segT);
|
|
|
|
#endif
|
|
|
|
|
2005-07-25 23:41:08 +08:00
|
|
|
/* Support for SHF_X86_64_LARGE */
|
2016-04-01 20:07:50 +08:00
|
|
|
extern bfd_vma x86_64_section_letter (int, const char **);
|
2005-07-25 23:41:08 +08:00
|
|
|
#define md_elf_section_letter(LETTER, PTR_MSG) x86_64_section_letter (LETTER, PTR_MSG)
|
|
|
|
|
2024-10-04 15:42:13 +08:00
|
|
|
#ifdef OBJ_ELF
|
2018-08-31 19:31:08 +08:00
|
|
|
extern void x86_cleanup (void);
|
|
|
|
#define md_cleanup() x86_cleanup ()
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
|
gas: x86: synthesize CFI for hand-written asm
This patch adds support in GAS to create generic GAS instructions
(a.k.a., the ginsn) for the x86 backend (AMD64 ABI only at this time).
Using this ginsn infrastructure, GAS can then synthesize CFI for
hand-written asm for x86_64.
A ginsn is a target-independent representation of the machine
instructions. One machine instruction may need one or more ginsn.
This patch also adds skeleton support for printing ginsn in the listing
output for debugging purposes.
Since the current use-case of ginsn is to synthesize CFI, the x86 target
needs to generate ginsns necessary for the following machine
instructions only:
- All change of flow instructions, including all conditional and
unconditional branches, call and return from functions.
- All register saves and unsaves to the stack.
- All instructions affecting the two registers that could potentially
be used as the base register for CFA tracking. For SCFI, the base
register for CFA tracking is limited to REG_SP and REG_FP only for
now.
The representation of ginsn is kept simple:
- GAS instruction has GINSN_NUM_SRC_OPNDS (defined to be 2 at this time)
number of source operands and one destination operand at this time.
- GAS instruction uses DWARF register numbers in its representation and
does not track register size.
- GAS instructions carry location information (file name and line
number).
- GAS instructions are ID's with a natural number in order of their
addtion to the list. This can be used as a proxy for the static
program order of the corresponding machine instructions.
Note that, GAS instruction (ginsn) format does not support
GINSN_TYPE_PUSH and GINSN_TYPE_POP. Some architectures, like aarch64,
do not have push and pop instructions, but rather STP/LDP/STR/LDR etc.
instructions. Further these instructions have a variety of addressing
modes, like offset, pre-indexing and post-indexing etc. Among other
things, one of differences in these addressing modes is _when_ the addr
register is updated with the result of the address calculation: before
or after the memory operation. To best support such needs, the generic
instructions like GINSN_TYPE_LOAD, GINSN_TYPE_STORE together with
GINSN_TYPE_ADD, and GINSN_TYPE_SUB may be used.
The functionality provided in ginsn.c and scfi.c is compiled in when a
target defines TARGET_USE_SCFI and TARGET_USE_GINSN. This can be
revisited later when there are other use-cases of creating ginsn's in
GAS, apart from the current use-case of synthesizing CFI for
hand-written asm.
Support is added only for System V AMD64 ABI for ELF at this time. If
the user enables SCFI with --32, GAS issues an error:
"Fatal error: SCFI is not supported for this ABI"
For synthesizing (DWARF) CFI, the SCFI machinery requires the programmer
to adhere to some pre-requisites for their asm:
- Hand-written asm block must begin with a .type foo, @function
It is highly recommended to, additionally, also ensure that:
- Hand-written asm block ends with a .size foo, .-foo
The SCFI machinery encodes some rules which align with the standard
calling convention specified by the ABI. Apart from the rules, the SCFI
machinery employs some heuristics. For example:
- The base register for CFA tracking may be either REG_SP or REG_FP.
- If the base register for CFA tracking is REG_SP, the precise amount of
stack usage (and hence, the value of REG_SP) must be known at all times.
- If using dynamic stack allocation, the function must switch to
FP-based CFA. This means using instructions like the following (in
AMD64) in prologue:
pushq %rbp
movq %rsp, %rbp
and analogous instructions in epilogue.
- Save and Restore of callee-saved registers must be symmetrical.
However, the SCFI machinery at this time only warns if any such
asymmetry is seen.
These heuristics/rules are architecture-independent and are meant to
employed for all architectures/ABIs using SCFI in the future.
gas/
* Makefile.am: Add new files.
* Makefile.in: Regenerated.
* as.c (defined): Handle documentation and listing option for
ginsns and SCFI.
* config/obj-elf.c (obj_elf_size): Invoke ginsn_data_end.
(obj_elf_type): Invoke ginsn_data_begin.
* config/tc-i386.c (x86_scfi_callee_saved_p): New function.
(ginsn_prefix_66H_p): Likewise.
(ginsn_dw2_regnum): Likewise.
(x86_ginsn_addsub_reg_mem): Likewise.
(x86_ginsn_addsub_mem_reg): Likewise.
(x86_ginsn_alu_imm): Likewise.
(x86_ginsn_move): Likewise.
(x86_ginsn_lea): Likewise.
(x86_ginsn_jump): Likewise.
(x86_ginsn_jump_cond): Likewise.
(x86_ginsn_enter): Likewise.
(x86_ginsn_safe_to_skip): Likewise.
(x86_ginsn_unhandled): Likewise.
(x86_ginsn_new): New functionality to generate ginsns.
(md_assemble): Invoke x86_ginsn_new.
(s_insn): Likewise.
(i386_target_format): Add hard error for usage of SCFI with non AMD64 ABIs.
* config/tc-i386.h (TARGET_USE_GINSN): New definition.
(TARGET_USE_SCFI): Likewise.
(SCFI_MAX_REG_ID): Likewise.
(REG_FP): Likewise.
(REG_SP): Likewise.
(SCFI_INIT_CFA_OFFSET): Likewise.
(SCFI_CALLEE_SAVED_REG_P): Likewise.
(x86_scfi_callee_saved_p): Likewise.
* gas/listing.h (LISTING_GINSN_SCFI): New define for ginsn and
SCFI.
* gas/read.c (read_a_source_file): Close SCFI processing at end
of file read.
* gas/scfidw2gen.c (scfi_process_cfi_label): Add implementation.
(scfi_process_cfi_signal_frame): Likewise.
* subsegs.h (struct frch_ginsn_data): New forward declaration.
(struct frchain): New member for ginsn data.
* gas/subsegs.c (subseg_set_rest): Initialize the new member.
* symbols.c (colon): Invoke ginsn_frob_label to convey
user-defined labels to ginsn infrastructure.
* ginsn.c: New file.
* ginsn.h: New file.
* scfi.c: New file.
* scfi.h: New file.
2024-01-15 17:00:31 +08:00
|
|
|
#define TARGET_USE_GINSN 1
|
|
|
|
/* Allow GAS to synthesize DWARF CFI for hand-written asm.
|
|
|
|
PS: TARGET_USE_CFIPOP is a pre-condition. */
|
|
|
|
#define TARGET_USE_SCFI 1
|
|
|
|
/* Identify the maximum DWARF register number of all the registers being
|
|
|
|
tracked for SCFI. This is the last DWARF register number of the set
|
|
|
|
of SP, BP, and all callee-saved registers. For AMD64, this means
|
|
|
|
R15 (15). Use SCFI_CALLEE_SAVED_REG_P to identify which registers
|
|
|
|
are callee-saved from this set. */
|
|
|
|
#define SCFI_MAX_REG_ID 15
|
|
|
|
/* Some ABIs, like AMD64, use stack for call instruction. For such an ABI,
|
|
|
|
identify the initial (CFA) offset from RSP at the entry of function. */
|
|
|
|
#define SCFI_INIT_CFA_OFFSET 8
|
|
|
|
|
|
|
|
#define SCFI_CALLEE_SAVED_REG_P(dw2reg) x86_scfi_callee_saved_p (dw2reg)
|
|
|
|
extern bool x86_scfi_callee_saved_p (uint32_t dw2reg_num);
|
|
|
|
|
2023-02-02 16:48:59 +08:00
|
|
|
/* Whether SFrame stack trace info is supported. */
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
extern bool x86_support_sframe_p (void);
|
|
|
|
#define support_sframe_p x86_support_sframe_p
|
|
|
|
|
2024-07-04 16:34:12 +08:00
|
|
|
/* The stack pointer DWARF register number for SFrame CFA tracking. */
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
extern unsigned int x86_sframe_cfa_sp_reg;
|
|
|
|
#define SFRAME_CFA_SP_REG x86_sframe_cfa_sp_reg
|
|
|
|
|
2024-07-04 16:34:12 +08:00
|
|
|
/* The frame pointer DWARF register number for SFrame CFA and FP tracking. */
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
extern unsigned int x86_sframe_cfa_fp_reg;
|
|
|
|
#define SFRAME_CFA_FP_REG x86_sframe_cfa_fp_reg
|
|
|
|
|
2024-07-04 16:34:12 +08:00
|
|
|
/* Whether SFrame return address tracking is needed. */
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
extern bool x86_sframe_ra_tracking_p (void);
|
|
|
|
#define sframe_ra_tracking_p x86_sframe_ra_tracking_p
|
|
|
|
|
2024-07-04 16:34:12 +08:00
|
|
|
/* The fixed offset from CFA for SFrame to recover the return address.
|
|
|
|
(useful only when SFrame RA tracking is not needed). */
|
gas: generate .sframe from CFI directives
Currently supported for x86_64 and aarch64 only.
[PS: Currently, the compiler has not been adapted to generate
".cfi_sections" with ".sframe" in it. The newly added command line
option of --gsframe provides an easy way to try out .sframe support
in the toolchain.]
gas interprets the CFI directives to generate DWARF-based .eh_frame
info. These internal DWARF structures are now consumed by
gen-sframe.[ch] sub-system to, in turn, create the SFrame unwind
information. These internal DWARF structures are read-only for the
purpose of SFrame unwind info generation.
SFrame unwind info generation does not impact .eh_frame unwind info
generation. Both .eh_frame and .sframe can co-exist in an ELF file,
if so desired by the user.
Recall that SFrame unwind information only contains the minimal
necessary information to generate backtraces and does not provide
information to recover all callee-saved registers. The reason being
that callee-saved registers other than FP are not needed for stack
unwinding, and hence are not included in the .sframe section.
Consequently, gen-sframe.[ch] only needs to interpret a subset of
DWARF opcodes in gas. More details follow.
[Set 1, Interpreted] The following opcodes are interpreted:
- DW_CFA_advance_loc
- DW_CFA_def_cfa
- DW_CFA_def_cfa_register
- DW_CFA_def_cfa_offset
- DW_CFA_offset
- DW_CFA_remember_state
- DW_CFA_restore_state
- DW_CFA_restore
[Set 2, Bypassed] The following opcodes are acknowledged but are not
necessary for generating SFrame unwind info:
- DW_CFA_undefined
- DW_CFA_same_value
Anything else apart from the two above-mentioned sets is skipped
altogether. This means that any function containing a CFI directive not
in Set 1 or Set 2 above, will not have any SFrame unwind information
generated for them. Holes in instructions covered by FREs of a single
FDE are not representable in the SFrame unwind format.
As few examples, following opcodes are not processed for .sframe
generation, and are skipped:
- .cfi_personality*
- .cfi_*lsda
- .cfi_escape
- .cfi_negate_ra_state
- ...
Not processing .cfi_escape, .cfi_negate_ra_state will cause SFrame
unwind information to be absent for SFrame FDEs that contain these CFI
directives, hence affecting the asynchronicity.
x86-64 and aarch64 backends need to have a few new definitions and
functions for .sframe generation. These provide gas with architecture
specific information like the SP/FP/RA register numbers and an
SFrame-specific ABI marker.
Lastly, the patch also implements an optimization for size, where
specific fragments containing SFrame FRE start address and SFrame FDE
function are fixed up. This is similar to other similar optimizations
in gas, where fragments are sized and fixed up when the associated
symbols can be resolved. This optimization is controlled by a #define
SFRAME_FRE_TYPE_SELECTION_OPT and should be easy to turn off if needed.
The optimization is on by default for both x86_64 and aarch64.
ChangeLog:
* gas/Makefile.am: Include gen-sframe.c and sframe-opt.c.
* gas/Makefile.in: Regenerated.
* gas/as.h (enum _relax_state): Add new state rs_sframe.
(sframe_estimate_size_before_relax): New function.
(sframe_relax_frag): Likewise.
(sframe_convert_frag): Likewise.
* gas/config/tc-aarch64.c (aarch64_support_sframe_p): New
definition.
(aarch64_sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(md_begin): Set values of sp/fp/ra registers.
* gas/config/tc-aarch64.h (aarch64_support_sframe_p): New
declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(SFRAME_CFA_RA_REG): Likewise.
(aarch64_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(aarch64_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(aarch64_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.c (x86_support_sframe_p): New definition.
(x86_sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
* gas/config/tc-i386.h (x86_support_sframe_p): New declaration.
(support_sframe_p): Likewise.
(SFRAME_CFA_SP_REG): Likewise.
(SFRAME_CFA_FP_REG): Likewise.
(x86_sframe_ra_tracking_p): Likewise.
(sframe_ra_tracking_p): Likewise.
(x86_sframe_cfa_ra_offset): Likewise.
(sframe_cfa_ra_offset): Likewise.
(x86_sframe_get_abi_arch): Likewise.
(sframe_get_abi_arch): Likewise.
* gas/config/tc-xtensa.c (unrelaxed_frag_max_size): Add case for
rs_sframe.
* gas/doc/as.texi: Add .sframe to the documentation for
.cfi_sections.
* gas/dw2gencfi.c (cfi_finish): Create a .sframe section.
* gas/dw2gencfi.h (CFI_EMIT_sframe): New definition.
* gas/write.c (cvt_frag_to_fill): Handle rs_sframe.
(relax_segment): Likewise.
* gas/gen-sframe.c: New file.
* gas/gen-sframe.h: New file.
* gas/sframe-opt.c: New file.
2022-11-16 07:06:46 +08:00
|
|
|
extern offsetT x86_sframe_cfa_ra_offset (void);
|
|
|
|
#define sframe_cfa_ra_offset x86_sframe_cfa_ra_offset
|
|
|
|
|
|
|
|
/* The abi/arch indentifier for SFrame. */
|
|
|
|
extern unsigned char x86_sframe_get_abi_arch (void);
|
|
|
|
#define sframe_get_abi_arch x86_sframe_get_abi_arch
|
|
|
|
|
2018-08-31 19:31:08 +08:00
|
|
|
#endif
|
|
|
|
|
2004-10-18 20:32:13 +08:00
|
|
|
#ifdef TE_PE
|
|
|
|
|
|
|
|
#define O_secrel O_md1
|
|
|
|
|
|
|
|
#define TC_DWARF2_EMIT_OFFSET tc_pe_dwarf2_emit_offset
|
|
|
|
void tc_pe_dwarf2_emit_offset (symbolS *, unsigned int);
|
|
|
|
|
|
|
|
#endif /* TE_PE */
|
|
|
|
|
2009-04-20 14:31:50 +08:00
|
|
|
/* X_add_symbol:X_op_symbol (Intel mode only) */
|
|
|
|
#define O_full_ptr O_md2
|
|
|
|
|
2012-02-21 17:13:02 +08:00
|
|
|
#ifdef OBJ_MACH_O
|
|
|
|
|
|
|
|
#define TC_FORCE_RELOCATION(FIX) (obj_mach_o_force_reloc (FIX))
|
|
|
|
|
|
|
|
#define TC_FORCE_RELOCATION_SUB_SAME(FIX,SEG) \
|
|
|
|
(obj_mach_o_force_reloc_sub_same (FIX, SEG))
|
|
|
|
|
|
|
|
#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX,SEG) \
|
|
|
|
(obj_mach_o_force_reloc_sub_local (FIX, SEG))
|
|
|
|
|
|
|
|
#define TC_VALIDATE_FIX_SUB(FIX, SEG) 1
|
|
|
|
|
|
|
|
#endif /* OBJ_MACH_O */
|
|
|
|
|
2002-08-09 20:37:41 +08:00
|
|
|
#endif /* TC_I386 */
|