Compare commits

...

5 Commits

Author SHA1 Message Date
H.J. Lu
651dc85243 Gold: Don't fail on R_X86_64_[REX_]GOTPCRELX relocations
This patch updates gold to treat the R_X86_64_GOTPCRELX and
R_X86_64_REX_GOTPCRELX relocations proposed in

https://groups.google.com/forum/#!topic/x86-64-abi/n9AWHogmVY0

the same as R_X86_64_GOTPCREL.  FIXME: Gold should perform the
transformations as suggested.

elfcpp/

	* x86_64.h (R_X86_64_GOTPCRELX): New.
	(R_X86_64_REX_GOTPCRELX): Likewise.

gold/

	* x86_64.cc (Target_x86_64<size>::Scan::get_reference_flags):
	Treat R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX the same
	as R_X86_64_GOTPCREL.
	(Target_x86_64<size>::Scan::local): Likewise.
	(Target_x86_64<size>::Scan::possible_function_pointer_reloc):
	Likewise.
	(Target_x86_64<size>::Scan::global): Likewise.
	(Target_x86_64<size>::Relocate::relocate): Likewise.
	(Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc):
	Likewise.
2015-10-21 16:45:47 -07:00
H.J. Lu
a85711043c Gold: Don't fail on R_386_GOT32X relocation
This patch updates gold to treat the R_386_GOT32X relocation proposed in

https://groups.google.com/forum/#!topic/ia32-abi/GbJJskkid4I

the same as R_386_GOT32.  FIXME: Gold should perform the transformations
as suggested.

elfcpp/

	* i386.h (R_386_GOT32X): New.

gold/

	* i386.cc (Target_i386::Scan::get_reference_flags(): Treat
	R_386_GOT32X the same as R_386_GOT32.
	(Target_i386::Scan::local): Likewise.
	(Target_i386::Scan::possible_function_pointer_reloc): Likewise.
	(Target_i386::Scan::global): Likewise.
	(Target_i386::Relocate::relocate): Likewise.
	(Target_i386::Relocatable_size_for_reloc::get_size_for_reloc):
	Likewise.
2015-10-21 16:45:47 -07:00
H.J. Lu
2d1d9ed8d3 Add "-z call-nop=PADDING" option to ld
The ld linker can transform indirect call to a locally defined function,
foo, via its GOT slot, to either "NOP call foo" or "call foo NOP" where
NOP is a 1-byte NOP padding.  This patch adds a "-z call-nop=PADDING"
option to x86 ld to control 1-byte NOP padding for x86 call instruction.
PADDING is one of prefix-addr, prefix-nop, suffix-nop, prefix-NUMBER or
suffix-NUMBER.

bfd/

	* elf32-i386.c (elf_i386_convert_load): Use call_nop_byte and
	check call_nop_as_suffix for 1-byte NOP padding to pad call.
	* elf64-x86-64.c (elf_x86_64_convert_load): Likewise.

include/

	* bfdlink.h (bfd_link_info): Add call_nop_as_suffix and
	call_nop_byte.

ld/

	* ld/ld.texinfo: Document "-z call-nop=PADDING" option.
	* emulparams/call_nop.sh: New file.
	* emulparams/elf_i386_be.sh: Source
	${srcdir}/emulparams/call_nop.sh.
	* emulparams/elf_i386_chaos.sh: Likewise.
	* emulparams/elf_i386_ldso.sh: Likewise.
	* emulparams/elf_i386_vxworks.sh: Likewise.
	* emulparams/elf_iamcu.sh: Likewise.
	* emulparams/elf_k1om.sh: Likewise.
	* emulparams/elf_l1om.sh: Likewise.
	* emulparams/elf_x86_64.sh: Likewise.
	* emultempl/elf32.em (gld${EMULATION_NAME}_before_parse): Set
	link_info.call_nop_byte if $CALL_NOP_BYTE isn't empty.

ld/testsuite/

	* ld-i386/call3.s: New file.
	* ld-i386/call3a.d: Likewise.
	* ld-i386/call3b.d: Likewise.
	* ld-i386/call3c.d: Likewise.
	* ld-i386/call3d.d: Likewise.
	* ld-i386/call3e.d: Likewise.
	* ld-i386/call3f.d: Likewise.
	* ld-i386/call3g.d: Likewise.
	* ld-i386/call3h.d: Likewise.
	* ld-i386/load1-nacl.d: Likewise.
	* ld-x86-64/call1.s: Likewise.
	* ld-x86-64/call1a.d: Likewise.
	* ld-x86-64/call1b.d: Likewise.
	* ld-x86-64/call1c.d: Likewise.
	* ld-x86-64/call1d.d: Likewise.
	* ld-x86-64/call1e.d: Likewise.
	* ld-x86-64/call1f.d: Likewise.
	* ld-x86-64/call1g.d: Likewise.
	* ld-x86-64/call1h.d: Likewise.
	* ld-x86-64/call1i.d: Likewise.
	* ld-x86-64/load1a-nacl.d: Likewise.
	* ld-x86-64/load1b-nacl.d: Likewise.
	* ld-x86-64/load1c-nacl.d: Likewise.
	* ld-x86-64/load1d-nacl.d: Likewise.
2015-10-21 16:45:47 -07:00
H.J. Lu
37c0370059 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-21 16:45:47 -07:00
H.J. Lu
91d9e98ebf Add R_386_GOT32X support to gas and ld
This patch adds support for the R_386_GOT32X relocation proposed in

https://groups.google.com/forum/#!topic/ia32-abi/GbJJskkid4I

to gas and ld.  It updates gas to generate R_386_GOT32X relocation for
memory operand, foo@GOT[(%reg)].  We must encode "mov foo@GOT, %eax"
with the 0x8b opcode, instead of the 0xb8 opcode, so that it can be
transformed to "lea foo, %eax".  With the locally defined symbol, foo,
we convert

   mov foo@GOT[(%reg1)], %reg2
to
   lea foo[@GOTOFF(%reg1)], %reg2

and convert

   call/jmp *foo@GOT[(%reg)]
to

   nop call foo/jmp foo nop

When PIC is false, convert

   test %reg1, foo@GOT[(%reg2)]
to
   test $foo, %reg1

and convert

binop foo@GOT[(%reg1)], %reg2

to

binop $foo, %reg2

where binop is one of adc, add, and, cmp, or, sbb, sub, xor instructions.

bfd/

	* elf32-i386.c: Include opcode/i386.h.
	(elf_howto_table): Add R_386_GOT32X.
	(R_386_ext2): Replace R_386_IRELATIVE with R_386_GOT32X.
	(elf_i386_reloc_type_lookup): Handle BFD_RELOC_386_GOT32X.
	(need_convert_mov_to_lea): Renamed to ...
	(need_convert_load): This.
	(elf_i386_check_relocs): Handle R_386_GOT32X.  Replace
	need_convert_mov_to_lea with need_convert_load.
	(elf_i386_gc_sweep_hook): Handle R_386_GOT32X.
	(elf_i386_size_dynamic_sections): Likewise.
	(elf_i386_relocate_section): Likewise.
	(elf_i386_convert_mov_to_lea): Renamed to ...
	(elf_i386_convert_load): This.  Replace need_convert_mov_to_lea
	with need_convert_load.  Support R_386_GOT32X transformations.
	* reloc.c (BFD_RELOC_386_GOT32X): New.
	* bfd-in2.h: Regenerated.
	* libbfd.h: Likewise.

gas/

	* config/tc-i386.c (tc_i386_fix_adjustable): Handle
	BFD_RELOC_386_GOT32X.
	(tc_gen_reloc): Likewise.
	(match_template): Force 0x8b encoding for "mov foo@GOT, %eax".
	(output_disp): Check for "call/jmp *mem", "mov mem, %reg",
	"test %reg, mem" and "binop mem, %reg" where binop is one of
	adc, add, and, cmp, or, sbb, sub, xor instructions.  Set
	fx_tcbit if the REX prefix is generated.  Set fx_tcbit2 if
	BFD_RELOC_386_GOT32X should be generated.
	(i386_validate_fix): Generate BFD_RELOC_386_GOT32X if fx_tcbit2
	is set.

gas/testsuite/

	* gas/i386/got.d: New file.
	* gas/i386/got.s: Likewise.
	* gas/i386/i386.exp: Run got.
	* gas/i386/localpic.d: Replace R_386_GOT32 with R_386_GOT32X.
	* gas/i386/mixed-mode-reloc32.d: Likewise.
	* gas/i386/reloc32.d: Likewise.

include/elf/

	* i386.h (R_386_GOT32X): New relocation.

ld/testsuite/

	* ld-i386/branch1.d: New file.
	* ld-i386/branch1.s: Likewise.
	* ld-i386/call1.d: Likewise.
	* ld-i386/call1.s: Likewise.
	* ld-i386/call2.d: Likewise.
	* ld-i386/call2.s: Likewise.
	* ld-i386/got1.dd: Likewise.
	* ld-i386/got1.out: Likewise.
	* ld-i386/got1a.S: Likewise.
	* ld-i386/got1b.c: Likewise.
	* ld-i386/got1c.c: Likewise.
	* ld-i386/got1d.S: Likewise.
	* ld-i386/jmp1.d: Likewise.
	* ld-i386/jmp1.s: Likewise.
	* ld-i386/jmp2.d: Likewise.
	* ld-i386/jmp2.s: Likewise.
	* ld-i386/load1.d: Likewise.
	* ld-i386/load1.s: Likewise.
	* ld-i386/load2.d: Likewise.
	* ld-i386/load2.s: Likewise.
	* ld-i386/load3.d: Likewise.
	* ld-i386/load3.s: Likewise.
	* ld-i386/load4.s: Likewise.
	* ld-i386/load4a.d: Likewise.
	* ld-i386/load4b.d: Likewise.
	* ld-i386/load5.s: Likewise.
	* ld-i386/load5a.d: Likewise.
	* ld-i386/load5b.d: Likewise.
	* ld-i386/load6.d: Likewise.
	* ld-i386/load6.s: Likewise.
	* ld-i386/i386.exp: Run branch1, call1, call2, jmp1, jmp2,
	load1, load2, load3, load4a, load4b, load5a, load5b and load6
	tests.  Run got1 test.
2015-10-21 16:45:47 -07:00
113 changed files with 2241 additions and 120 deletions

View File

@@ -3177,6 +3177,7 @@ instruction. */
BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_386_TLS_DESC_CALL,
BFD_RELOC_386_TLS_DESC, BFD_RELOC_386_TLS_DESC,
BFD_RELOC_386_IRELATIVE, BFD_RELOC_386_IRELATIVE,
BFD_RELOC_386_GOT32X,
/* x86-64/elf relocations */ /* x86-64/elf relocations */
BFD_RELOC_X86_64_GOT32, BFD_RELOC_X86_64_GOT32,
@@ -3208,6 +3209,8 @@ instruction. */
BFD_RELOC_X86_64_IRELATIVE, BFD_RELOC_X86_64_IRELATIVE,
BFD_RELOC_X86_64_PC32_BND, BFD_RELOC_X86_64_PC32_BND,
BFD_RELOC_X86_64_PLT32_BND, BFD_RELOC_X86_64_PLT32_BND,
BFD_RELOC_X86_64_GOTPCRELX,
BFD_RELOC_X86_64_REX_GOTPCRELX,
/* ns32k relocations */ /* ns32k relocations */
BFD_RELOC_NS32K_IMM_8, BFD_RELOC_NS32K_IMM_8,

View File

@@ -29,6 +29,7 @@
#include "objalloc.h" #include "objalloc.h"
#include "hashtab.h" #include "hashtab.h"
#include "dwarf2.h" #include "dwarf2.h"
#include "opcode/i386.h"
/* 386 uses REL relocations instead of RELA. */ /* 386 uses REL relocations instead of RELA. */
#define USE_REL 1 #define USE_REL 1
@@ -146,9 +147,12 @@ static reloc_howto_type elf_howto_table[]=
HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, HOWTO(R_386_IRELATIVE, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_IRELATIVE", bfd_elf_generic_reloc, "R_386_IRELATIVE",
TRUE, 0xffffffff, 0xffffffff, FALSE), TRUE, 0xffffffff, 0xffffffff, FALSE),
HOWTO(R_386_GOT32X, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,
bfd_elf_generic_reloc, "R_386_GOT32X",
TRUE, 0xffffffff, 0xffffffff, FALSE),
/* Another gap. */ /* Another gap. */
#define R_386_ext2 (R_386_IRELATIVE + 1 - R_386_tls_offset) #define R_386_ext2 (R_386_GOT32X + 1 - R_386_tls_offset)
#define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2) #define R_386_vt_offset (R_386_GNU_VTINHERIT - R_386_ext2)
/* GNU extension to record C++ vtable hierarchy. */ /* GNU extension to record C++ vtable hierarchy. */
@@ -332,6 +336,10 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
TRACE ("BFD_RELOC_386_IRELATIVE"); TRACE ("BFD_RELOC_386_IRELATIVE");
return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset]; return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
case BFD_RELOC_386_GOT32X:
TRACE ("BFD_RELOC_386_GOT32X");
return &elf_howto_table[R_386_GOT32X - R_386_tls_offset];
case BFD_RELOC_VTABLE_INHERIT: case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT"); TRACE ("BFD_RELOC_VTABLE_INHERIT");
return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset]; return &elf_howto_table[R_386_GNU_VTINHERIT - R_386_vt_offset];
@@ -1468,7 +1476,7 @@ elf_i386_tls_transition (struct bfd_link_info *info, bfd *abfd,
/* Rename some of the generic section flags to better document how they /* Rename some of the generic section flags to better document how they
are used here. */ are used here. */
#define need_convert_mov_to_lea sec_flg0 #define need_convert_load sec_flg0
/* Look through the relocs for a section during the first phase, and /* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure linkage calculate needed space in the global offset table, procedure linkage
@@ -1580,6 +1588,7 @@ elf_i386_check_relocs (bfd *abfd,
case R_386_PC32: case R_386_PC32:
case R_386_PLT32: case R_386_PLT32:
case R_386_GOT32: case R_386_GOT32:
case R_386_GOT32X:
if (htab->elf.dynobj == NULL) if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd; htab->elf.dynobj = abfd;
if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info))
@@ -1637,6 +1646,7 @@ elf_i386_check_relocs (bfd *abfd,
/* Fall through */ /* Fall through */
case R_386_GOT32: case R_386_GOT32:
case R_386_GOT32X:
case R_386_TLS_GD: case R_386_TLS_GD:
case R_386_TLS_GOTDESC: case R_386_TLS_GOTDESC:
case R_386_TLS_DESC_CALL: case R_386_TLS_DESC_CALL:
@@ -1647,7 +1657,10 @@ elf_i386_check_relocs (bfd *abfd,
switch (r_type) switch (r_type)
{ {
default: default:
case R_386_GOT32: tls_type = GOT_NORMAL; break; case R_386_GOT32:
case R_386_GOT32X:
tls_type = GOT_NORMAL;
break;
case R_386_TLS_GD: tls_type = GOT_TLS_GD; break; case R_386_TLS_GD: tls_type = GOT_TLS_GD; break;
case R_386_TLS_GOTDESC: case R_386_TLS_GOTDESC:
case R_386_TLS_DESC_CALL: case R_386_TLS_DESC_CALL:
@@ -1948,9 +1961,9 @@ do_size:
return FALSE; return FALSE;
} }
if (r_type == R_386_GOT32 if ((r_type == R_386_GOT32 || r_type == R_386_GOT32X)
&& (h == NULL || h->type != STT_GNU_IFUNC)) && (h == NULL || h->type != STT_GNU_IFUNC))
sec->need_convert_mov_to_lea = 1; sec->need_convert_load = 1;
} }
return TRUE; return TRUE;
@@ -2074,6 +2087,7 @@ elf_i386_gc_sweep_hook (bfd *abfd,
case R_386_TLS_IE: case R_386_TLS_IE:
case R_386_TLS_GOTIE: case R_386_TLS_GOTIE:
case R_386_GOT32: case R_386_GOT32:
case R_386_GOT32X:
if (h != NULL) if (h != NULL)
{ {
if (h->got.refcount > 0) if (h->got.refcount > 0)
@@ -2718,14 +2732,27 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf)
return TRUE; return TRUE;
} }
/* Convert /* With the local symbol, foo, we convert
mov foo@GOT(%reg), %reg mov foo@GOT[(%reg1)], %reg2
to to
lea foo@GOTOFF(%reg), %reg lea foo[@GOTOFF(%reg1)], %reg2
with the local symbol, foo. */ and convert
call/jmp *foo@GOT[(%reg)]
to
nop call foo/jmp foo nop
When PIC is false, convert
test %reg1, foo@GOT[(%reg2)]
to
test $foo, %reg1
and convert
binop foo@GOT[(%reg1)], %reg2
to
binop $foo, %reg2
where binop is one of adc, add, and, cmp, or, sbb, sub, xor
instructions. */
static bfd_boolean static bfd_boolean
elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec, elf_i386_convert_load (bfd *abfd, asection *sec,
struct bfd_link_info *link_info) struct bfd_link_info *link_info)
{ {
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
@@ -2743,7 +2770,7 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
/* Nothing to do if there is no need or no output. */ /* Nothing to do if there is no need or no output. */
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|| sec->need_convert_mov_to_lea == 0 || sec->need_convert_load == 0
|| bfd_is_abs_section (sec->output_section)) || bfd_is_abs_section (sec->output_section))
return TRUE; return TRUE;
@@ -2777,32 +2804,92 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
unsigned int r_symndx = ELF32_R_SYM (irel->r_info); unsigned int r_symndx = ELF32_R_SYM (irel->r_info);
unsigned int indx; unsigned int indx;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
unsigned int opcode;
unsigned int modrm;
bfd_vma roff;
bfd_boolean baseless;
Elf_Internal_Sym *isym;
unsigned int addend;
unsigned int nop;
bfd_vma nop_offset;
if (r_type != R_386_GOT32) if (r_type != R_386_GOT32 && r_type != R_386_GOT32X)
continue; continue;
/* Get the symbol referred to by the reloc. */ roff = irel->r_offset;
if (roff < 2)
continue;
modrm = bfd_get_8 (abfd, contents + roff - 1);
baseless = (modrm & 0xc7) == 0x5;
if (r_type == R_386_GOT32X
&& baseless
&& bfd_link_pic (link_info))
{
/* For PIC, disallow R_386_GOT32X without a base register
since we don't know what the GOT base is. Allow
R_386_GOT32 for existing object files. */
const char *name;
if (r_symndx < symtab_hdr->sh_info)
{
isym = bfd_sym_from_r_symndx (&htab->sym_cache, abfd,
r_symndx);
name = bfd_elf_sym_name (abfd, symtab_hdr, isym, NULL);
}
else
{
indx = r_symndx - symtab_hdr->sh_info;
h = elf_sym_hashes (abfd)[indx];
BFD_ASSERT (h != NULL);
name = h->root.root.string;
}
(*_bfd_error_handler)
(_("%B: direct GOT relocation R_386_GOT32X against `%s' without base register can not be used when making a shared object"),
abfd, name);
goto error_return;
}
opcode = bfd_get_8 (abfd, contents + roff - 2);
/* It is OK to convert mov to lea. */
if (opcode != 0x8b)
{
/* Only convert R_386_GOT32X relocation for call, jmp or
one of adc, add, and, cmp, or, sbb, sub, test, xor
instructions. */
if (r_type != R_386_GOT32X)
continue;
/* It is OK to convert indirect branch to direct branch. It
is OK to convert adc, add, and, cmp, or, sbb, sub, test,
xor only when PIC is false. */
if (opcode != 0xff && bfd_link_pic (link_info))
continue;
}
/* Try to convert R_386_GOT32 and R_386_GOT32X. Get the symbol
referred to by the reloc. */
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
{ {
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->sym_cache, isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx); abfd, r_symndx);
/* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */ /* STT_GNU_IFUNC must keep GOT32 relocations. */
if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
&& irel->r_offset >= 2 continue;
&& bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
{ h = NULL;
bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2); if (opcode == 0x0ff)
irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); /* Convert "call/jmp *foo@GOT[(%reg)]". */
if (local_got_refcounts != NULL goto convert_branch;
&& local_got_refcounts[r_symndx] > 0) else
local_got_refcounts[r_symndx] -= 1; /* Convert "mov foo@GOT[(%reg1)], %reg2",
changed_contents = TRUE; "test %reg1, foo@GOT(%reg2)" and
changed_relocs = TRUE; "binop foo@GOT[(%reg1)], %reg2". */
} goto convert_load;
continue;
} }
indx = r_symndx - symtab_hdr->sh_info; indx = r_symndx - symtab_hdr->sh_info;
@@ -2813,22 +2900,153 @@ elf_i386_convert_mov_to_lea (bfd *abfd, asection *sec,
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
/* STT_GNU_IFUNC must keep R_386_GOT32 relocation. We also avoid /* STT_GNU_IFUNC must keep GOT32 relocations. */
optimizing _DYNAMIC since ld.so may use its link-time address. */ if (h->type == STT_GNU_IFUNC)
if ((h->root.type == bfd_link_hash_defined continue;
|| h->root.type == bfd_link_hash_defweak)
&& h->type != STT_GNU_IFUNC if (opcode == 0xff)
&& h != htab->elf.hdynamic
&& SYMBOL_REFERENCES_LOCAL (link_info, h)
&& irel->r_offset >= 2
&& bfd_get_8 (abfd, contents + irel->r_offset - 2) == 0x8b)
{ {
bfd_put_8 (abfd, 0x8d, contents + irel->r_offset - 2); /* We have "call/jmp *foo@GOT[(%reg)]". */
irel->r_info = ELF32_R_INFO (r_symndx, R_386_GOTOFF); if ((h->root.type == bfd_link_hash_defined
if (h->got.refcount > 0) || h->root.type == bfd_link_hash_defweak)
h->got.refcount -= 1; && SYMBOL_REFERENCES_LOCAL (link_info, h))
changed_contents = TRUE; {
changed_relocs = TRUE; /* The function is locally defined. */
convert_branch:
addend = bfd_get_32 (abfd, contents + roff);
/* Addend for R_386_GOT32X relocation must be 0. */
if (addend != 0)
continue;
/* Convert R_386_GOT32X to R_386_PC32. */
if (modrm == 0x15 || (modrm & 0xf8) == 0x90)
{
/* Convert to "nop call foo". ADDR_PREFIX_OPCODE
is a nop prefix. */
modrm = 0xe8;
nop = link_info->call_nop_byte;
if (link_info->call_nop_as_suffix)
{
nop_offset = roff + 3;
irel->r_offset -= 1;
}
else
nop_offset = roff - 2;
}
else
{
/* Convert to "jmp foo nop". */
modrm = 0xe9;
nop = NOP_OPCODE;
nop_offset = roff + 3;
irel->r_offset -= 1;
}
bfd_put_8 (abfd, nop, contents + nop_offset);
bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
/* When converting to PC-relative relocation, we
need to adjust addend by -4. */
bfd_put_32 (abfd, -4, contents + irel->r_offset);
irel->r_info = ELF32_R_INFO (r_symndx, R_386_PC32);
if (h)
{
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else
{
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
changed_contents = TRUE;
changed_relocs = TRUE;
}
}
else
{
/* We have "mov foo@GOT[(%re1g)], %reg2",
"test %reg1, foo@GOT(%reg2)" and
"binop foo@GOT[(%reg1)], %reg2".
Avoid optimizing _DYNAMIC since ld.so may use its
link-time address. */
if (h == htab->elf.hdynamic)
continue;
if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
&& SYMBOL_REFERENCES_LOCAL (link_info, h))
{
convert_load:
if (opcode == 0x8b)
{
/* Convert "mov foo@GOT(%reg1), %reg2" to
"lea foo@GOTOFF(%reg1), %reg2". */
if (r_type == R_386_GOT32X
&& (baseless || !bfd_link_pic (link_info)))
{
r_type = R_386_32;
/* For R_386_32, convert
"lea foo@GOTOFF(%reg1), %reg2" to
"lea foo@GOT, %reg2". */
if (!baseless)
{
modrm = 0x5 | (modrm & 0x38);
bfd_put_8 (abfd, modrm, contents + roff - 1);
}
}
else
r_type = R_386_GOTOFF;
opcode = 0x8d;
}
else
{
/* Addend for R_386_GOT32X relocation must be 0. */
addend = bfd_get_32 (abfd, contents + roff);
if (addend != 0)
continue;
if (opcode == 0x85)
{
/* Convert "test %reg1, foo@GOT(%reg2)" to
"test $foo, %reg1". */
modrm = 0xc0 | (modrm & 0x38) >> 3;
opcode = 0xf7;
}
else
{
/* Convert "binop foo@GOT(%reg1), %reg2" to
"binop $foo, %reg2". */
modrm = (0xc0
| (modrm & 0x38) >> 3
| (opcode & 0x3c));
opcode = 0x81;
}
bfd_put_8 (abfd, modrm, contents + roff - 1);
r_type = R_386_32;
}
bfd_put_8 (abfd, opcode, contents + roff - 2);
irel->r_info = ELF32_R_INFO (r_symndx, r_type);
if (h)
{
if (h->got.refcount > 0)
h->got.refcount -= 1;
}
else
{
if (local_got_refcounts != NULL
&& local_got_refcounts[r_symndx] > 0)
local_got_refcounts[r_symndx] -= 1;
}
changed_contents = TRUE;
changed_relocs = TRUE;
}
} }
} }
@@ -2914,7 +3132,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
{ {
struct elf_dyn_relocs *p; struct elf_dyn_relocs *p;
if (!elf_i386_convert_mov_to_lea (ibfd, s, info)) if (!elf_i386_convert_load (ibfd, s, info))
return FALSE; return FALSE;
for (p = ((struct elf_dyn_relocs *) for (p = ((struct elf_dyn_relocs *)
@@ -3664,6 +3882,7 @@ elf_i386_relocate_section (bfd *output_bfd,
goto do_relocation; goto do_relocation;
case R_386_GOT32: case R_386_GOT32:
case R_386_GOT32X:
base_got = htab->elf.sgot; base_got = htab->elf.sgot;
off = h->got.offset; off = h->got.offset;
@@ -3741,7 +3960,61 @@ elf_i386_relocate_section (bfd *output_bfd,
eh = (struct elf_i386_link_hash_entry *) h; eh = (struct elf_i386_link_hash_entry *) h;
switch (r_type) switch (r_type)
{ {
case R_386_GOT32X:
/* Avoid optimizing _DYNAMIC since ld.so may use its
link-time address. */
if (h == htab->elf.hdynamic)
goto r_386_got32;
if (bfd_link_pic (info))
{
/* It is OK to convert mov to lea and convert indirect
branch to direct branch. It is OK to convert adc,
add, and, cmp, or, sbb, sub, test, xor only when PIC
is false. */
unsigned int opcode;
opcode = bfd_get_8 (abfd, contents + rel->r_offset - 2);
if (opcode != 0x8b && opcode != 0xff)
goto r_386_got32;
}
/* Resolve "mov GOT[(%reg)], %reg",
"call/jmp *GOT[(%reg)]", "test %reg, foo@GOT[(%reg)]"
and "binop foo@GOT[(%reg)], %reg". */
if (h == NULL
|| (h->plt.offset == (bfd_vma) -1
&& h->got.offset == (bfd_vma) -1)
|| htab->elf.sgotplt == NULL)
abort ();
offplt = (htab->elf.sgotplt->output_section->vma
+ htab->elf.sgotplt->output_offset);
/* It is relative to .got.plt section. */
if (h->got.offset != (bfd_vma) -1)
/* Use GOT entry. */
relocation = (htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset
+ h->got.offset - offplt);
else
/* Use GOTPLT entry. */
relocation = (h->plt.offset / plt_entry_size - 1 + 3) * 4;
if (!bfd_link_pic (info))
{
/* If not PIC, add the .got.plt section address for
baseless adressing. */
unsigned int modrm;
modrm = bfd_get_8 (abfd, contents + rel->r_offset - 1);
if ((modrm & 0xc7) == 0x5)
relocation += offplt;
}
unresolved_reloc = FALSE;
break;
case R_386_GOT32: case R_386_GOT32:
r_386_got32:
/* Relocation is to the entry for this symbol in the global /* Relocation is to the entry for this symbol in the global
offset table. */ offset table. */
if (htab->elf.sgot == NULL) if (htab->elf.sgot == NULL)

View File

@@ -31,6 +31,7 @@
#include "dwarf2.h" #include "dwarf2.h"
#include "libiberty.h" #include "libiberty.h"
#include "opcode/i386.h"
#include "elf/x86-64.h" #include "elf/x86-64.h"
#ifdef CORE_HEADER #ifdef CORE_HEADER
@@ -176,12 +177,18 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_PLT32_BND, 0, 2, 32, TRUE, 0, complain_overflow_signed, HOWTO(R_X86_64_PLT32_BND, 0, 2, 32, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", FALSE, 0xffffffff, 0xffffffff, bfd_elf_generic_reloc, "R_X86_64_PLT32_BND", FALSE, 0xffffffff, 0xffffffff,
TRUE), TRUE),
HOWTO(R_X86_64_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_GOTPCRELX", FALSE, 0xffffffff,
0xffffffff, TRUE),
HOWTO(R_X86_64_REX_GOTPCRELX, 0, 2, 32, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_REX_GOTPCRELX", FALSE, 0xffffffff,
0xffffffff, TRUE),
/* We have a gap in the reloc numbers here. /* We have a gap in the reloc numbers here.
R_X86_64_standard counts the number up to this point, and R_X86_64_standard counts the number up to this point, and
R_X86_64_vt_offset is the value to subtract from a reloc type of R_X86_64_vt_offset is the value to subtract from a reloc type of
R_X86_64_GNU_VT* to form an index into this table. */ R_X86_64_GNU_VT* to form an index into this table. */
#define R_X86_64_standard (R_X86_64_PLT32_BND + 1) #define R_X86_64_standard (R_X86_64_REX_GOTPCRELX + 1)
#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard) #define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
/* GNU extension to record C++ vtable hierarchy. */ /* GNU extension to record C++ vtable hierarchy. */
@@ -253,8 +260,10 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, }, { BFD_RELOC_X86_64_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
{ BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, }, { BFD_RELOC_X86_64_TLSDESC, R_X86_64_TLSDESC, },
{ BFD_RELOC_X86_64_IRELATIVE, R_X86_64_IRELATIVE, }, { BFD_RELOC_X86_64_IRELATIVE, R_X86_64_IRELATIVE, },
{ BFD_RELOC_X86_64_PC32_BND, R_X86_64_PC32_BND,}, { BFD_RELOC_X86_64_PC32_BND, R_X86_64_PC32_BND, },
{ BFD_RELOC_X86_64_PLT32_BND, R_X86_64_PLT32_BND,}, { BFD_RELOC_X86_64_PLT32_BND, R_X86_64_PLT32_BND, },
{ BFD_RELOC_X86_64_GOTPCRELX, R_X86_64_GOTPCRELX, },
{ BFD_RELOC_X86_64_REX_GOTPCRELX, R_X86_64_REX_GOTPCRELX, },
{ BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, }, { BFD_RELOC_VTABLE_INHERIT, R_X86_64_GNU_VTINHERIT, },
{ BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, }, { BFD_RELOC_VTABLE_ENTRY, R_X86_64_GNU_VTENTRY, },
}; };
@@ -1545,7 +1554,7 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
/* Rename some of the generic section flags to better document how they /* Rename some of the generic section flags to better document how they
are used here. */ are used here. */
#define need_convert_mov_to_lea sec_flg0 #define need_convert_load sec_flg0
/* Look through the relocs for a section during the first phase, and /* Look through the relocs for a section during the first phase, and
calculate needed space in the global offset table, procedure calculate needed space in the global offset table, procedure
@@ -1726,6 +1735,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_32S: case R_X86_64_32S:
case R_X86_64_PC64: case R_X86_64_PC64:
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTPCREL64: case R_X86_64_GOTPCREL64:
if (htab->elf.dynobj == NULL) if (htab->elf.dynobj == NULL)
htab->elf.dynobj = abfd; htab->elf.dynobj = abfd;
@@ -1779,6 +1790,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_GOT32: case R_X86_64_GOT32:
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_TLSGD: case R_X86_64_TLSGD:
case R_X86_64_GOT64: case R_X86_64_GOT64:
case R_X86_64_GOTPCREL64: case R_X86_64_GOTPCREL64:
@@ -2151,9 +2164,11 @@ do_size:
return FALSE; return FALSE;
} }
if (r_type == R_X86_64_GOTPCREL if ((r_type == R_X86_64_GOTPCREL
|| r_type == R_X86_64_GOTPCRELX
|| r_type == R_X86_64_REX_GOTPCRELX)
&& (h == NULL || h->type != STT_GNU_IFUNC)) && (h == NULL || h->type != STT_GNU_IFUNC))
sec->need_convert_mov_to_lea = 1; sec->need_convert_load = 1;
} }
return TRUE; return TRUE;
@@ -2279,6 +2294,8 @@ elf_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_X86_64_GOTTPOFF: case R_X86_64_GOTTPOFF:
case R_X86_64_GOT32: case R_X86_64_GOT32:
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOT64: case R_X86_64_GOT64:
case R_X86_64_GOTPCREL64: case R_X86_64_GOTPCREL64:
case R_X86_64_GOTPLT64: case R_X86_64_GOTPLT64:
@@ -2953,15 +2970,28 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h,
return TRUE; return TRUE;
} }
/* Convert /* With the local symbol, foo, we convert
mov foo@GOTPCREL(%rip), %reg mov foo@GOTPCREL(%rip), %reg
to to
lea foo(%rip), %reg lea foo(%rip), %reg
with the local symbol, foo. */ 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. */
static bfd_boolean static bfd_boolean
elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec, elf_x86_64_convert_load (bfd *abfd, asection *sec,
struct bfd_link_info *link_info) struct bfd_link_info *link_info)
{ {
Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *internal_relocs;
@@ -2979,7 +3009,7 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
/* Nothing to do if there is no need or no output. */ /* Nothing to do if there is no need or no output. */
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC) if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|| sec->need_convert_mov_to_lea == 0 || sec->need_convert_load == 0
|| bfd_is_abs_section (sec->output_section)) || bfd_is_abs_section (sec->output_section))
return TRUE; return TRUE;
@@ -3017,22 +3047,45 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
asection *tsec; asection *tsec;
char symtype; char symtype;
bfd_vma toff, roff; bfd_vma toff, roff;
bfd_signed_vma raddend;
unsigned int opcode; unsigned int opcode;
unsigned int modrm;
if (r_type != R_X86_64_GOTPCREL) if (r_type != R_X86_64_GOTPCREL
&& r_type != R_X86_64_GOTPCRELX
&& r_type != R_X86_64_REX_GOTPCRELX)
continue; continue;
roff = irel->r_offset; roff = irel->r_offset;
if (roff < (r_type == R_X86_64_REX_GOTPCRELX ? 3 : 2))
continue;
if (roff < 2) raddend = irel->r_addend;
/* Addend for 32-bit PC-relative relocation must be -4. */
if (raddend != -4)
continue; continue;
opcode = bfd_get_8 (abfd, contents + roff - 2); opcode = bfd_get_8 (abfd, contents + roff - 2);
/* PR ld/18591: Don't convert R_X86_64_GOTPCREL relocation if it /* It is OK to convert mov to lea. */
isn't for mov instruction. */
if (opcode != 0x8b) if (opcode != 0x8b)
continue; {
/* Only convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX
for mov call, jmp or one of adc, add, and, cmp, or, sbb,
sub, test, xor instructions. */
if (r_type != R_X86_64_GOTPCRELX
&& r_type != R_X86_64_REX_GOTPCRELX)
continue;
/* It is OK to convert indirect branch to direct branch. */
if (opcode != 0xff)
{
/* It is OK to convert adc, add, and, cmp, or, sbb, sub,
test, xor only when PIC is false. */
if (bfd_link_pic (link_info))
continue;
}
}
/* Get the symbol referred to by the reloc. */ /* Get the symbol referred to by the reloc. */
if (r_symndx < symtab_hdr->sh_info) if (r_symndx < symtab_hdr->sh_info)
@@ -3044,8 +3097,8 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
symtype = ELF_ST_TYPE (isym->st_info); symtype = ELF_ST_TYPE (isym->st_info);
/* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation and /* STT_GNU_IFUNC must keep GOTPCREL relocations and skip
skip relocation against undefined symbols. */ relocation against undefined symbols. */
if (symtype == STT_GNU_IFUNC || isym->st_shndx == SHN_UNDEF) if (symtype == STT_GNU_IFUNC || isym->st_shndx == SHN_UNDEF)
continue; continue;
@@ -3071,9 +3124,9 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
|| h->root.type == bfd_link_hash_warning) || h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link; h = (struct elf_link_hash_entry *) h->root.u.i.link;
/* STT_GNU_IFUNC must keep R_X86_64_GOTPCREL relocation. We also /* STT_GNU_IFUNC must keep GOTPCREL relocations. We also
avoid optimizing _DYNAMIC since ld.so may use its link-time avoid optimizing GOTPCREL relocations againt _DYNAMIC
address. */ since ld.so may use its link-time address. */
if ((h->root.type == bfd_link_hash_defined if ((h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak) || h->root.type == bfd_link_hash_defweak)
&& h->type != STT_GNU_IFUNC && h->type != STT_GNU_IFUNC
@@ -3107,17 +3160,17 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
access is presumed to be an offset from "sym"; The access is presumed to be an offset from "sym"; The
location of interest is just "sym". */ location of interest is just "sym". */
if (symtype == STT_SECTION) if (symtype == STT_SECTION)
toff += irel->r_addend; toff += raddend;
toff = _bfd_merged_section_offset (abfd, &tsec, toff = _bfd_merged_section_offset (abfd, &tsec,
elf_section_data (tsec)->sec_info, elf_section_data (tsec)->sec_info,
toff); toff);
if (symtype != STT_SECTION) if (symtype != STT_SECTION)
toff += irel->r_addend; toff += raddend;
} }
else else
toff += irel->r_addend; toff += raddend;
/* Don't convert if R_X86_64_PC32 relocation overflows. */ /* Don't convert if R_X86_64_PC32 relocation overflows. */
if (tsec->output_section == sec->output_section) if (tsec->output_section == sec->output_section)
@@ -3148,8 +3201,8 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
} }
} }
/* Don't convert R_X86_64_GOTPCREL if TSEC isn't placed after /* Don't convert GOTPCREL relocations if TSEC isn't placed
SEC. */ after SEC. */
if (asect == NULL) if (asect == NULL)
continue; continue;
@@ -3160,8 +3213,90 @@ elf_x86_64_convert_mov_to_lea (bfd *abfd, asection *sec,
continue; continue;
} }
bfd_put_8 (abfd, 0x8d, contents + roff - 2); if (opcode == 0xff)
irel->r_info = htab->r_info (r_symndx, R_X86_64_PC32); {
/* We have "call/jmp *foo@GOTPCREL(%rip)". */
unsigned int nop;
unsigned int disp;
bfd_vma nop_offset;
/* Convert R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX to
R_X86_64_PC32. */
modrm = bfd_get_8 (abfd, contents + roff - 1);
if (modrm == 0x25)
{
/* Convert to "jmp foo nop". */
modrm = 0xe9;
nop = NOP_OPCODE;
nop_offset = irel->r_offset + 3;
disp = bfd_get_32 (abfd, contents + irel->r_offset);
irel->r_offset -= 1;
bfd_put_32 (abfd, disp, contents + irel->r_offset);
}
else
{
/* Convert to "nop call foo". ADDR_PREFIX_OPCODE
is a nop prefix. */
modrm = 0xe8;
nop = link_info->call_nop_byte;
if (link_info->call_nop_as_suffix)
{
nop_offset = irel->r_offset + 3;
disp = bfd_get_32 (abfd, contents + irel->r_offset);
irel->r_offset -= 1;
bfd_put_32 (abfd, disp, contents + irel->r_offset);
}
else
nop_offset = irel->r_offset - 2;
}
bfd_put_8 (abfd, nop, contents + nop_offset);
bfd_put_8 (abfd, modrm, contents + irel->r_offset - 1);
r_type = R_X86_64_PC32;
}
else
{
if (opcode == 0x8b)
{
/* Convert "mov foo@GOTPCREL(%rip), %reg" to
"lea foo(%rip), %reg". */
opcode = 0x8d;
r_type = R_X86_64_PC32;
}
else
{
modrm = bfd_get_8 (abfd, contents + roff - 1);
if (opcode == 0x85)
{
/* Convert "test %reg, foo@GOTPCREL(%rip)" to
"test $foo, %reg". */
modrm = 0xc0 | (modrm & 0x38) >> 3;
opcode = 0xf7;
}
else
{
/* Convert "binop foo@GOTPCREL(%rip), %reg" to
"binop $foo, %reg". */
modrm = 0xc0 | (modrm & 0x38) >> 3 | (opcode & 0x3c);
opcode = 0x81;
}
bfd_put_8 (abfd, modrm, contents + roff - 1);
if (r_type == R_X86_64_REX_GOTPCRELX)
{
/* Move the R bit to the B bit in REX byte. */
unsigned int rex = bfd_get_8 (abfd, contents + roff - 3);
rex = (rex & ~REX_R) | (rex & REX_R) >> 2;
bfd_put_8 (abfd, rex, contents + roff - 3);
}
/* No addend for R_X86_64_32S relocation. */
irel->r_addend = 0;
r_type = R_X86_64_32S;
}
bfd_put_8 (abfd, opcode, contents + roff - 2);
}
irel->r_info = htab->r_info (r_symndx, r_type);
changed_contents = TRUE; changed_contents = TRUE;
changed_relocs = TRUE; changed_relocs = TRUE;
@@ -3264,7 +3399,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
{ {
struct elf_dyn_relocs *p; struct elf_dyn_relocs *p;
if (!elf_x86_64_convert_mov_to_lea (ibfd, s, info)) if (!elf_x86_64_convert_load (ibfd, s, info))
return FALSE; return FALSE;
for (p = (struct elf_dyn_relocs *) for (p = (struct elf_dyn_relocs *)
@@ -3985,6 +4120,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
goto do_relocation; goto do_relocation;
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTPCREL64: case R_X86_64_GOTPCREL64:
base_got = htab->elf.sgot; base_got = htab->elf.sgot;
off = h->got.offset; off = h->got.offset;
@@ -4053,6 +4190,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
/* Relocation is to the entry for this symbol in the global /* Relocation is to the entry for this symbol in the global
offset table. */ offset table. */
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_GOTPCRELX:
case R_X86_64_REX_GOTPCRELX:
case R_X86_64_GOTPCREL64: case R_X86_64_GOTPCREL64:
/* Use global offset table entry as symbol value. */ /* Use global offset table entry as symbol value. */
case R_X86_64_GOTPLT64: case R_X86_64_GOTPLT64:
@@ -4158,7 +4297,10 @@ elf_x86_64_relocate_section (bfd *output_bfd,
relocation = base_got->output_section->vma relocation = base_got->output_section->vma
+ base_got->output_offset + off; + base_got->output_offset + off;
if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64) if (r_type != R_X86_64_GOTPCREL
&& r_type != R_X86_64_GOTPCRELX
&& r_type != R_X86_64_REX_GOTPCRELX
&& r_type != R_X86_64_GOTPCREL64)
relocation -= htab->elf.sgotplt->output_section->vma relocation -= htab->elf.sgotplt->output_section->vma
- htab->elf.sgotplt->output_offset; - htab->elf.sgotplt->output_offset;

View File

@@ -1292,6 +1292,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_386_TLS_DESC_CALL", "BFD_RELOC_386_TLS_DESC_CALL",
"BFD_RELOC_386_TLS_DESC", "BFD_RELOC_386_TLS_DESC",
"BFD_RELOC_386_IRELATIVE", "BFD_RELOC_386_IRELATIVE",
"BFD_RELOC_386_GOT32X",
"BFD_RELOC_X86_64_GOT32", "BFD_RELOC_X86_64_GOT32",
"BFD_RELOC_X86_64_PLT32", "BFD_RELOC_X86_64_PLT32",
"BFD_RELOC_X86_64_COPY", "BFD_RELOC_X86_64_COPY",
@@ -1321,6 +1322,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_IRELATIVE", "BFD_RELOC_X86_64_IRELATIVE",
"BFD_RELOC_X86_64_PC32_BND", "BFD_RELOC_X86_64_PC32_BND",
"BFD_RELOC_X86_64_PLT32_BND", "BFD_RELOC_X86_64_PLT32_BND",
"BFD_RELOC_X86_64_GOTPCRELX",
"BFD_RELOC_X86_64_REX_GOTPCRELX",
"BFD_RELOC_NS32K_IMM_8", "BFD_RELOC_NS32K_IMM_8",
"BFD_RELOC_NS32K_IMM_16", "BFD_RELOC_NS32K_IMM_16",
"BFD_RELOC_NS32K_IMM_32", "BFD_RELOC_NS32K_IMM_32",

View File

@@ -2676,6 +2676,8 @@ ENUMX
BFD_RELOC_386_TLS_DESC BFD_RELOC_386_TLS_DESC
ENUMX ENUMX
BFD_RELOC_386_IRELATIVE BFD_RELOC_386_IRELATIVE
ENUMX
BFD_RELOC_386_GOT32X
ENUMDOC ENUMDOC
i386/elf relocations i386/elf relocations
@@ -2737,6 +2739,10 @@ ENUMX
BFD_RELOC_X86_64_PC32_BND BFD_RELOC_X86_64_PC32_BND
ENUMX ENUMX
BFD_RELOC_X86_64_PLT32_BND BFD_RELOC_X86_64_PLT32_BND
ENUMX
BFD_RELOC_X86_64_GOTPCRELX
ENUMX
BFD_RELOC_X86_64_REX_GOTPCRELX
ENUMDOC ENUMDOC
x86-64/elf relocations x86-64/elf relocations

View File

@@ -86,6 +86,7 @@ enum
R_386_TLS_DESC = 41, // TLS descriptor containing pointer to code and R_386_TLS_DESC = 41, // TLS descriptor containing pointer to code and
// to argument, returning TLS offset for symbol // to argument, returning TLS offset for symbol
R_386_IRELATIVE = 42, // Adjust indirectly by program base R_386_IRELATIVE = 42, // Adjust indirectly by program base
R_386_GOT32X = 43, // 32 bit GOT entry, relaxable
// Used by Intel. // Used by Intel.
R_386_USED_BY_INTEL_200 = 200, R_386_USED_BY_INTEL_200 = 200,
// GNU vtable garbage collection extensions. // GNU vtable garbage collection extensions.

View File

@@ -94,6 +94,10 @@ enum
R_X86_64_RELATIVE64 = 38, // 64-bit adjust by program base R_X86_64_RELATIVE64 = 38, // 64-bit adjust by program base
R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix R_X86_64_PC32_BND = 39, // PC relative 32 bit signed with BND prefix
R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix R_X86_64_PLT32_BND = 40, // 32 bit PLT address with BND prefix
R_X86_64_GOTPCRELX = 41, // 32 bit signed PC relative offset to GOT
// without REX prefix, relaxable.
R_X86_64_REX_GOTPCRELX = 42, // 32 bit signed PC relative offset to GOT
// with REX prefix, relaxable.
// GNU vtable garbage collection extensions. // GNU vtable garbage collection extensions.
R_X86_64_GNU_VTINHERIT = 250, R_X86_64_GNU_VTINHERIT = 250,
R_X86_64_GNU_VTENTRY = 251 R_X86_64_GNU_VTENTRY = 251

View File

@@ -2928,6 +2928,7 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
|| fixP->fx_r_type == BFD_RELOC_386_GOTOFF || fixP->fx_r_type == BFD_RELOC_386_GOTOFF
|| fixP->fx_r_type == BFD_RELOC_386_PLT32 || fixP->fx_r_type == BFD_RELOC_386_PLT32
|| fixP->fx_r_type == BFD_RELOC_386_GOT32 || fixP->fx_r_type == BFD_RELOC_386_GOT32
|| fixP->fx_r_type == BFD_RELOC_386_GOT32X
|| fixP->fx_r_type == BFD_RELOC_386_TLS_GD || fixP->fx_r_type == BFD_RELOC_386_TLS_GD
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDM || fixP->fx_r_type == BFD_RELOC_386_TLS_LDM
|| fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32 || fixP->fx_r_type == BFD_RELOC_386_TLS_LDO_32
@@ -2941,6 +2942,8 @@ tc_i386_fix_adjustable (fixS *fixP ATTRIBUTE_UNUSED)
|| fixP->fx_r_type == BFD_RELOC_X86_64_PLT32 || fixP->fx_r_type == BFD_RELOC_X86_64_PLT32
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOT32 || fixP->fx_r_type == BFD_RELOC_X86_64_GOT32
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL || fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCREL
|| fixP->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX
|| fixP->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX
|| fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD || fixP->fx_r_type == BFD_RELOC_X86_64_TLSGD
|| fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD || fixP->fx_r_type == BFD_RELOC_X86_64_TLSLD
|| fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32 || fixP->fx_r_type == BFD_RELOC_X86_64_DTPOFF32
@@ -4791,6 +4794,10 @@ match_template (void)
} }
} }
/* Force 0x8b encoding for "mov foo@GOT, %eax". */
if (i.reloc[0] == BFD_RELOC_386_GOT32 && t->base_opcode == 0xa0)
continue;
/* We check register size if needed. */ /* We check register size if needed. */
check_register = t->opcode_modifier.checkregsize; check_register = t->opcode_modifier.checkregsize;
overlap0 = operand_type_and (i.types[0], operand_types[0]); overlap0 = operand_type_and (i.types[0], operand_types[0]);
@@ -7157,6 +7164,7 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
int size = disp_size (n); int size = disp_size (n);
int sign = i.types[n].bitfield.disp32s; int sign = i.types[n].bitfield.disp32s;
int pcrel = (i.flags[n] & Operand_PCrel) != 0; int pcrel = (i.flags[n] & Operand_PCrel) != 0;
fixS *fixP;
/* We can't have 8 bit displacement here. */ /* We can't have 8 bit displacement here. */
gas_assert (!i.types[n].bitfield.disp8); gas_assert (!i.types[n].bitfield.disp8);
@@ -7225,8 +7233,34 @@ output_disp (fragS *insn_start_frag, offsetT insn_start_off)
insn, and that is taken care of in other code. */ insn, and that is taken care of in other code. */
reloc_type = BFD_RELOC_X86_64_GOTPC32; reloc_type = BFD_RELOC_X86_64_GOTPC32;
} }
fix_new_exp (frag_now, p - frag_now->fr_literal, size, fixP = fix_new_exp (frag_now, p - frag_now->fr_literal,
i.op[n].disps, pcrel, reloc_type); size, i.op[n].disps, pcrel,
reloc_type);
/* Check for "call/jmp *mem", "mov mem, %reg",
"test %reg, mem" and "binop mem, %reg" where binop
is one of adc, add, and, cmp, or, sbb, sub, xor
instructions. */
if ((i.rm.mode == 2
|| (i.rm.mode == 0 && i.rm.regmem == 5))
&& ((i.operands == 1
&& i.tm.base_opcode == 0xff
&& (i.rm.reg == 2 || i.rm.reg == 4))
|| (i.operands == 2
&& (i.tm.base_opcode == 0x8b
|| i.tm.base_opcode == 0x85
|| (i.tm.base_opcode & 0xc7) == 0x03))))
{
if (object_64bit)
{
fixP->fx_tcbit = i.rex != 0;
if (i.base_reg
&& (i.base_reg->reg_num == RegRip
|| i.base_reg->reg_num == RegEip))
fixP->fx_tcbit2 = 1;
}
else
fixP->fx_tcbit2 = 1;
}
} }
} }
} }
@@ -10321,23 +10355,41 @@ s_bss (int ignore ATTRIBUTE_UNUSED)
void void
i386_validate_fix (fixS *fixp) i386_validate_fix (fixS *fixp)
{ {
if (fixp->fx_subsy && fixp->fx_subsy == GOT_symbol) if (fixp->fx_subsy)
{ {
if (fixp->fx_r_type == BFD_RELOC_32_PCREL) if (fixp->fx_subsy == GOT_symbol)
{ {
if (!object_64bit) if (fixp->fx_r_type == BFD_RELOC_32_PCREL)
abort (); {
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL; if (!object_64bit)
} abort ();
else #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
{ if (fixp->fx_tcbit2)
if (!object_64bit) fixp->fx_r_type = (fixp->fx_tcbit
fixp->fx_r_type = BFD_RELOC_386_GOTOFF; ? BFD_RELOC_X86_64_REX_GOTPCRELX
: BFD_RELOC_X86_64_GOTPCRELX);
else
#endif
fixp->fx_r_type = BFD_RELOC_X86_64_GOTPCREL;
}
else else
fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64; {
if (!object_64bit)
fixp->fx_r_type = BFD_RELOC_386_GOTOFF;
else
fixp->fx_r_type = BFD_RELOC_X86_64_GOTOFF64;
}
fixp->fx_subsy = 0;
} }
fixp->fx_subsy = 0;
} }
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
else if (!object_64bit)
{
if (fixp->fx_r_type == BFD_RELOC_386_GOT32
&& fixp->fx_tcbit2)
fixp->fx_r_type = BFD_RELOC_386_GOT32X;
}
#endif
} }
arelent * arelent *
@@ -10371,8 +10423,11 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_PLT32: case BFD_RELOC_X86_64_PLT32:
case BFD_RELOC_X86_64_GOT32: case BFD_RELOC_X86_64_GOT32:
case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_X86_64_GOTPCRELX:
case BFD_RELOC_X86_64_REX_GOTPCRELX:
case BFD_RELOC_386_PLT32: case BFD_RELOC_386_PLT32:
case BFD_RELOC_386_GOT32: case BFD_RELOC_386_GOT32:
case BFD_RELOC_386_GOT32X:
case BFD_RELOC_386_GOTOFF: case BFD_RELOC_386_GOTOFF:
case BFD_RELOC_386_GOTPC: case BFD_RELOC_386_GOTPC:
case BFD_RELOC_386_TLS_GD: case BFD_RELOC_386_TLS_GD:
@@ -10524,6 +10579,8 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
case BFD_RELOC_X86_64_PLT32: case BFD_RELOC_X86_64_PLT32:
case BFD_RELOC_X86_64_GOT32: case BFD_RELOC_X86_64_GOT32:
case BFD_RELOC_X86_64_GOTPCREL: case BFD_RELOC_X86_64_GOTPCREL:
case BFD_RELOC_X86_64_GOTPCRELX:
case BFD_RELOC_X86_64_REX_GOTPCRELX:
case BFD_RELOC_X86_64_TLSGD: case BFD_RELOC_X86_64_TLSGD:
case BFD_RELOC_X86_64_TLSLD: case BFD_RELOC_X86_64_TLSLD:
case BFD_RELOC_X86_64_GOTTPOFF: case BFD_RELOC_X86_64_GOTTPOFF:

View File

@@ -170,11 +170,12 @@ extern int tc_i386_fix_adjustable (struct fix *);
the .o file. GOTOFF and GOT32 do not need to be checked here because the .o file. GOTOFF and GOT32 do not need to be checked here because
they are not pcrel. .*/ they are not pcrel. .*/
#define TC_FORCE_RELOCATION_LOCAL(FIX) \ #define TC_FORCE_RELOCATION_LOCAL(FIX) \
(!(FIX)->fx_pcrel \ (!(FIX)->fx_pcrel \
|| (FIX)->fx_r_type == BFD_RELOC_386_PLT32 \ || (FIX)->fx_r_type == BFD_RELOC_386_PLT32 \
|| (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \ || (FIX)->fx_r_type == BFD_RELOC_386_GOTPC \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCREL \ || (FIX)->fx_r_type == BFD_RELOC_X86_64_GOTPCRELX \
|| (FIX)->fx_r_type == BFD_RELOC_X86_64_REX_GOTPCRELX \
|| TC_FORCE_RELOCATION (FIX)) || TC_FORCE_RELOCATION (FIX))
extern int i386_parse_name (char *, expressionS *, char *); extern int i386_parse_name (char *, expressionS *, char *);

View File

@@ -0,0 +1,29 @@
#objdump: -dwr
.*: +file format .*
Disassembly of section .text:
0+ <_start>:
[ ]*[a-f0-9]+: b8 00 00 00 00 mov \$0x0,%eax 1: R_386_GOT32 foo
[ ]*[a-f0-9]+: 8b 05 00 00 00 00 mov 0x0,%eax 7: R_386_GOT32X foo
[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax d: R_386_GOT32X foo
[ ]*[a-f0-9]+: 05 00 00 00 00 add \$0x0,%eax 12: R_386_GOT32 foo
[ ]*[a-f0-9]+: 03 05 00 00 00 00 add 0x0,%eax 18: R_386_GOT32X foo
[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 1e: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 24: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 2a: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 30: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 36: R_386_GOT32X foo
[ ]*[a-f0-9]+: b8 00 00 00 00 mov \$0x0,%eax 3b: R_386_GOT32 foo
[ ]*[a-f0-9]+: 8b 05 00 00 00 00 mov 0x0,%eax 41: R_386_GOT32X foo
[ ]*[a-f0-9]+: 8b 80 00 00 00 00 mov 0x0\(%eax\),%eax 47: R_386_GOT32X foo
[ ]*[a-f0-9]+: 05 00 00 00 00 add \$0x0,%eax 4c: R_386_GOT32 foo
[ ]*[a-f0-9]+: 03 05 00 00 00 00 add 0x0,%eax 52: R_386_GOT32X foo
[ ]*[a-f0-9]+: 03 80 00 00 00 00 add 0x0\(%eax\),%eax 58: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 90 00 00 00 00 call \*0x0\(%eax\) 5e: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 call \*0x0 64: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff a0 00 00 00 00 jmp \*0x0\(%eax\) 6a: R_386_GOT32X foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmp \*0x0 70: R_386_GOT32X foo
#pass

View File

@@ -0,0 +1,29 @@
.text
_start:
movl $foo@GOT, %eax
movl foo@GOT, %eax
movl foo@GOT(%eax), %eax
addl $foo@GOT, %eax
addl foo@GOT, %eax
addl foo@GOT(%eax), %eax
call *foo@GOT
call *foo@GOT(%eax)
jmp *foo@GOT
jmp *foo@GOT(%eax)
.intel_syntax noprefix
mov eax, offset foo@got
mov eax, DWORD PTR [foo@GOT]
mov eax, DWORD PTR [eax + foo@GOT]
add eax, offset foo@got
add eax, DWORD PTR [foo@GOT]
add eax, DWORD PTR [eax + foo@GOT]
call DWORD PTR [eax + foo@GOT]
call DWORD PTR [foo@GOT]
jmp DWORD PTR [eax + foo@GOT]
jmp DWORD PTR [foo@GOT]

View File

@@ -404,6 +404,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_32_check]]
run_dump_test "relax-3" run_dump_test "relax-3"
run_dump_test "relax-4" run_dump_test "relax-4"
run_dump_test "got"
if {![istarget "*-*-nacl*"]} then { if {![istarget "*-*-nacl*"]} then {
run_dump_test "iamcu-1" run_dump_test "iamcu-1"
run_dump_test "iamcu-2" run_dump_test "iamcu-2"
@@ -778,6 +780,8 @@ if [expr ([istarget "i*86-*-*"] || [istarget "x86_64-*-*"]) && [gas_64_check]] t
run_dump_test "x86-64-jump" run_dump_test "x86-64-jump"
run_dump_test "x86-64-branch-2" run_dump_test "x86-64-branch-2"
run_list_test "x86-64-branch-3" "-al -mintel64" run_list_test "x86-64-branch-3" "-al -mintel64"
run_dump_test "x86-64-gotpcrel"
} }
set ASFLAGS "$old_ASFLAGS" set ASFLAGS "$old_ASFLAGS"

View File

@@ -0,0 +1,27 @@
#source: ../x86-64-gotpcrel.s
#objdump: -dwr
#name: x86-64 (ILP32) gotpcrel
.*: +file format .*
Disassembly of section .text:
0+ <_start>:
[ ]*[a-f0-9]+: 48 c7 c0 00 00 00 00 mov \$0x0,%rax 3: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 04 25 00 00 00 00 mov 0x0,%rax b: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 16 <_start\+0x16> 12: R_X86_64_REX_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: 48 8b 81 00 00 00 00 mov 0x0\(%rcx\),%rax 19: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 callq \*0x0\(%rip\) # 23 <_start\+0x23> 1f: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff 90 00 00 00 00 callq \*0x0\(%rax\) 25: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmpq \*0x0\(%rip\) # 2f <_start\+0x2f> 2b: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff a1 00 00 00 00 jmpq \*0x0\(%rcx\) 31: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 c7 c0 00 00 00 00 mov \$0x0,%rax 38: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 04 25 00 00 00 00 mov 0x0,%rax 40: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 4b <_start\+0x4b> 47: R_X86_64_REX_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: 48 8b 81 00 00 00 00 mov 0x0\(%rcx\),%rax 4e: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 callq \*0x0\(%rip\) # 58 <_start\+0x58> 54: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff 90 00 00 00 00 callq \*0x0\(%rax\) 5a: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmpq \*0x0\(%rip\) # 64 <_start\+0x64> 60: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff a1 00 00 00 00 jmpq \*0x0\(%rcx\) 66: R_X86_64_GOTPCREL foo
#pass

View File

@@ -1,10 +1,10 @@
#source: ../x86-64-localpic.s #source: ../x86-64-localpic.s
#readelf: -rs #readelf: -rsW
#name: x86-64 (ILP32) local PIC #name: x86-64 (ILP32) local PIC
Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries: Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym.Value Sym. Name \+ Addend +Offset +Info +Type +Sym. Value +Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ R_X86_64_GOTPCREL +[0-9a-f]+ +foo - 4 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
#... #...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
#pass #pass

View File

@@ -3,7 +3,7 @@
Relocation section '.rel.text' at offset 0x[0-9a-f]+ contains 1 entries: Relocation section '.rel.text' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym.Value Sym. Name Offset Info Type Sym.Value Sym. Name
[0-9a-f]+ +[0-9a-f]+ R_386_GOT32 +[0-9a-f]+ +foo [0-9a-f]+ +[0-9a-f]+ R_386_GOT32X +[0-9a-f]+ +foo
#... #...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
#pass #pass

View File

@@ -6,9 +6,9 @@
RELOCATION RECORDS FOR \[.text\]: RELOCATION RECORDS FOR \[.text\]:
OFFSET[ ]+TYPE[ ]+VALUE[ ]* OFFSET[ ]+TYPE[ ]+VALUE[ ]*
[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]*
[0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*
[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]*
[0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*
[0-9a-f]+[ ]+R_386_GOT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_GOT32X[ ]+xtrn[ ]*
[0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]* [0-9a-f]+[ ]+R_386_PLT32[ ]+xtrn[ ]*

View File

@@ -18,7 +18,7 @@ Disassembly of section \.text:
.*[ ]+R_386_PC32[ ]+xtrn .*[ ]+R_386_PC32[ ]+xtrn
.*[ ]+R_386_PC8[ ]+xtrn .*[ ]+R_386_PC8[ ]+xtrn
.*[ ]+R_386_GOT32[ ]+xtrn .*[ ]+R_386_GOT32[ ]+xtrn
.*[ ]+R_386_GOT32[ ]+xtrn .*[ ]+R_386_GOT32X[ ]+xtrn
.*[ ]+R_386_GOTOFF[ ]+xtrn .*[ ]+R_386_GOTOFF[ ]+xtrn
.*[ ]+R_386_GOTOFF[ ]+xtrn .*[ ]+R_386_GOTOFF[ ]+xtrn
.*[ ]+R_386_GOTPC[ ]+_GLOBAL_OFFSET_TABLE_ .*[ ]+R_386_GOTPC[ ]+_GLOBAL_OFFSET_TABLE_

View File

@@ -0,0 +1,25 @@
#objdump: -dwr
.*: +file format .*
Disassembly of section .text:
0+ <_start>:
[ ]*[a-f0-9]+: 48 c7 c0 00 00 00 00 mov \$0x0,%rax 3: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 04 25 00 00 00 00 mov 0x0,%rax b: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 16 <_start\+0x16> 12: R_X86_64_REX_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: 48 8b 81 00 00 00 00 mov 0x0\(%rcx\),%rax 19: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 callq \*0x0\(%rip\) # 23 <_start\+0x23> 1f: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff 90 00 00 00 00 callq \*0x0\(%rax\) 25: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmpq \*0x0\(%rip\) # 2f <_start\+0x2f> 2b: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff a1 00 00 00 00 jmpq \*0x0\(%rcx\) 31: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 c7 c0 00 00 00 00 mov \$0x0,%rax 38: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 04 25 00 00 00 00 mov 0x0,%rax 40: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: 48 8b 05 00 00 00 00 mov 0x0\(%rip\),%rax # 4b <_start\+0x4b> 47: R_X86_64_REX_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: 48 8b 81 00 00 00 00 mov 0x0\(%rcx\),%rax 4e: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 15 00 00 00 00 callq \*0x0\(%rip\) # 58 <_start\+0x58> 54: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff 90 00 00 00 00 callq \*0x0\(%rax\) 5a: R_X86_64_GOTPCREL foo
[ ]*[a-f0-9]+: ff 25 00 00 00 00 jmpq \*0x0\(%rip\) # 64 <_start\+0x64> 60: R_X86_64_GOTPCRELX foo-0x4
[ ]*[a-f0-9]+: ff a1 00 00 00 00 jmpq \*0x0\(%rcx\) 66: R_X86_64_GOTPCREL foo
#pass

View File

@@ -0,0 +1,23 @@
.text
_start:
movq $foo@GOTPCREL, %rax
movq foo@GOTPCREL, %rax
movq foo@GOTPCREL(%rip), %rax
movq foo@GOTPCREL(%rcx), %rax
call *foo@GOTPCREL(%rip)
call *foo@GOTPCREL(%rax)
jmp *foo@GOTPCREL(%rip)
jmp *foo@GOTPCREL(%rcx)
.intel_syntax noprefix
mov rax, offset foo@gotpcrel
mov rax, QWORD PTR [foo@GOTPCREL]
mov rax, QWORD PTR [rip + foo@GOTPCREL]
mov rax, QWORD PTR [rcx + foo@GOTPCREL]
call QWORD PTR [rip + foo@GOTPCREL]
call QWORD PTR [rax + foo@GOTPCREL]
jmp QWORD PTR [rip + foo@GOTPCREL]
jmp QWORD PTR [rcx + foo@GOTPCREL]

View File

@@ -1,9 +1,9 @@
#readelf: -rs #readelf: -rsW
#name: x86-64 local PIC #name: x86-64 local PIC
Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries: Relocation section '.rela.text' at offset 0x[0-9a-f]+ contains 1 entries:
Offset Info Type Sym. Value Sym. Name \+ Addend +Offset +Info +Type +Symbol's Value +Symbol's Name \+ Addend
[0-9a-f]+ +[0-9a-f]+ R_X86_64_GOTPCREL +[0-9a-f]+ +foo - 4 [0-9a-f]+ +[0-9a-f]+ R_X86_64_REX_GOTPCRELX +[0-9a-f]+ +foo - 4
#... #...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +NOTYPE +LOCAL +DEFAULT +[0-9]+ +foo
#pass #pass

View File

@@ -1690,6 +1690,7 @@ Target_i386::Scan::get_reference_flags(unsigned int r_type)
return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF; return Symbol::FUNCTION_CALL | Symbol::RELATIVE_REF;
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
// Absolute in GOT. // Absolute in GOT.
return Symbol::ABSOLUTE_REF; return Symbol::ABSOLUTE_REF;
@@ -1854,6 +1855,7 @@ Target_i386::Scan::local(Symbol_table* symtab,
break; break;
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
{ {
// We need GOT section. // We need GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout); Output_data_got<32, false>* got = target->got_section(symtab, layout);
@@ -2105,6 +2107,7 @@ Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
case elfcpp::R_386_8: case elfcpp::R_386_8:
case elfcpp::R_386_GOTOFF: case elfcpp::R_386_GOTOFF:
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
{ {
return true; return true;
} }
@@ -2266,6 +2269,7 @@ Target_i386::Scan::global(Symbol_table* symtab,
break; break;
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
{ {
// The symbol requires a GOT section. // The symbol requires a GOT section.
Output_data_got<32, false>* got = target->got_section(symtab, layout); Output_data_got<32, false>* got = target->got_section(symtab, layout);
@@ -2834,6 +2838,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
break; break;
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
// Convert // Convert
// mov foo@GOT(%reg), %reg // mov foo@GOT(%reg), %reg
// to // to
@@ -3617,6 +3622,7 @@ Target_i386::Relocatable_size_for_reloc::get_size_for_reloc(
case elfcpp::R_386_32: case elfcpp::R_386_32:
case elfcpp::R_386_PC32: case elfcpp::R_386_PC32:
case elfcpp::R_386_GOT32: case elfcpp::R_386_GOT32:
case elfcpp::R_386_GOT32X:
case elfcpp::R_386_PLT32: case elfcpp::R_386_PLT32:
case elfcpp::R_386_GOTOFF: case elfcpp::R_386_GOTOFF:
case elfcpp::R_386_GOTPC: case elfcpp::R_386_GOTPC:

View File

@@ -2191,6 +2191,8 @@ Target_x86_64<size>::Scan::get_reference_flags(unsigned int r_type)
case elfcpp::R_X86_64_GOT32: case elfcpp::R_X86_64_GOT32:
case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL64:
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_GOTPLT64:
// Absolute in GOT. // Absolute in GOT.
return Symbol::ABSOLUTE_REF; return Symbol::ABSOLUTE_REF;
@@ -2475,6 +2477,8 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
case elfcpp::R_X86_64_GOT32: case elfcpp::R_X86_64_GOT32:
case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL64:
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_GOTPLT64:
{ {
// The symbol requires a GOT section. // The symbol requires a GOT section.
@@ -2485,7 +2489,9 @@ Target_x86_64<size>::Scan::local(Symbol_table* symtab,
// mov foo@GOTPCREL(%rip), %reg // mov foo@GOTPCREL(%rip), %reg
// to lea foo(%rip), %reg. // to lea foo(%rip), %reg.
// in Relocate::relocate. // in Relocate::relocate.
if (r_type == elfcpp::R_X86_64_GOTPCREL if ((r_type == elfcpp::R_X86_64_GOTPCREL
|| r_type == elfcpp::R_X86_64_GOTPCRELX
|| r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
&& reloc.get_r_offset() >= 2 && reloc.get_r_offset() >= 2
&& !is_ifunc) && !is_ifunc)
{ {
@@ -2713,6 +2719,8 @@ Target_x86_64<size>::Scan::possible_function_pointer_reloc(unsigned int r_type)
case elfcpp::R_X86_64_GOT32: case elfcpp::R_X86_64_GOT32:
case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL64:
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_GOTPLT64:
{ {
return true; return true;
@@ -2901,6 +2909,8 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
case elfcpp::R_X86_64_GOT32: case elfcpp::R_X86_64_GOT32:
case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL64:
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_GOTPLT64:
{ {
// The symbol requires a GOT entry. // The symbol requires a GOT entry.
@@ -2910,7 +2920,9 @@ Target_x86_64<size>::Scan::global(Symbol_table* symtab,
// mov foo@GOTPCREL(%rip), %reg // mov foo@GOTPCREL(%rip), %reg
// to lea foo(%rip), %reg. // to lea foo(%rip), %reg.
// in Relocate::relocate, then there is nothing to do here. // in Relocate::relocate, then there is nothing to do here.
if (r_type == elfcpp::R_X86_64_GOTPCREL if ((r_type == elfcpp::R_X86_64_GOTPCREL
|| r_type == elfcpp::R_X86_64_GOTPCRELX
|| r_type == elfcpp::R_X86_64_REX_GOTPCRELX)
&& reloc.get_r_offset() >= 2 && reloc.get_r_offset() >= 2
&& Target_x86_64<size>::can_convert_mov_to_lea(gsym)) && Target_x86_64<size>::can_convert_mov_to_lea(gsym))
{ {
@@ -3538,6 +3550,8 @@ Target_x86_64<size>::Relocate::relocate(
break; break;
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
{ {
// Convert // Convert
// mov foo@GOTPCREL(%rip), %reg // mov foo@GOTPCREL(%rip), %reg
@@ -4320,6 +4334,8 @@ Target_x86_64<size>::Relocatable_size_for_reloc::get_size_for_reloc(
case elfcpp::R_X86_64_GOT64: case elfcpp::R_X86_64_GOT64:
case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL64:
case elfcpp::R_X86_64_GOTPCREL: case elfcpp::R_X86_64_GOTPCREL:
case elfcpp::R_X86_64_GOTPCRELX:
case elfcpp::R_X86_64_REX_GOTPCRELX:
case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_GOTPLT64:
return 8; return 8;

View File

@@ -434,6 +434,12 @@ struct bfd_link_info
/* TRUE if generation of .interp/PT_INTERP should be suppressed. */ /* TRUE if generation of .interp/PT_INTERP should be suppressed. */
unsigned int nointerp: 1; unsigned int nointerp: 1;
/* TRUE if generate a 1-byte NOP as suffix for x86 call instruction. */
unsigned int call_nop_as_suffix : 1;
/* The 1-byte NOP for x86 call instruction. */
char call_nop_byte;
/* Char that may appear as the first char of a symbol, but should be /* Char that may appear as the first char of a symbol, but should be
skipped (like symbol_leading_char) when looking up symbols in skipped (like symbol_leading_char) when looking up symbols in
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */ wrap_hash. Used by PowerPC Linux for 'dot' symbols. */

View File

@@ -66,6 +66,8 @@ START_RELOC_NUMBERS (elf_i386_reloc_type)
RELOC_NUMBER (R_386_TLS_DESC_CALL,40) RELOC_NUMBER (R_386_TLS_DESC_CALL,40)
RELOC_NUMBER (R_386_TLS_DESC, 41) RELOC_NUMBER (R_386_TLS_DESC, 41)
RELOC_NUMBER (R_386_IRELATIVE, 42) /* Adjust indirectly by program base */ RELOC_NUMBER (R_386_IRELATIVE, 42) /* Adjust indirectly by program base */
/* Load from 32 bit GOT entry, relaxable. */
RELOC_NUMBER (R_386_GOT32X, 43)
/* Used by Intel. */ /* Used by Intel. */
RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200) RELOC_NUMBER (R_386_USED_BY_INTEL_200, 200)

View File

@@ -72,10 +72,16 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
RELOC_NUMBER (R_X86_64_TLSDESC, 36) /* 2x64-bit TLS descriptor. */ RELOC_NUMBER (R_X86_64_TLSDESC, 36) /* 2x64-bit TLS descriptor. */
RELOC_NUMBER (R_X86_64_IRELATIVE, 37) /* Adjust indirectly by program base */ RELOC_NUMBER (R_X86_64_IRELATIVE, 37) /* Adjust indirectly by program base */
RELOC_NUMBER (R_X86_64_RELATIVE64, 38) /* 64bit adjust by program base */ RELOC_NUMBER (R_X86_64_RELATIVE64, 38) /* 64bit adjust by program base */
RELOC_NUMBER (R_X86_64_PC32_BND, 39) /* PC relative 32 bit RELOC_NUMBER (R_X86_64_PC32_BND, 39) /* PC relative 32 bit
signed with BND prefix */ signed with BND prefix */
RELOC_NUMBER (R_X86_64_PLT32_BND, 40) /* 32 bit PLT address with RELOC_NUMBER (R_X86_64_PLT32_BND, 40) /* 32 bit PLT address with
BND prefix */ BND prefix */
/* Load from 32 bit signed pc relative offset to GOT entry without
REX prefix, relaxable. */
RELOC_NUMBER (R_X86_64_GOTPCRELX, 41)
/* Load from 32 bit signed pc relative offset to GOT entry with
REX prefix, relaxable. */
RELOC_NUMBER (R_X86_64_REX_GOTPCRELX, 42)
RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */ RELOC_NUMBER (R_X86_64_GNU_VTINHERIT, 250) /* GNU C++ hack */
RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */ RELOC_NUMBER (R_X86_64_GNU_VTENTRY, 251) /* GNU C++ hack */
END_RELOC_NUMBERS (R_X86_64_max) END_RELOC_NUMBERS (R_X86_64_max)

48
ld/emulparams/call_nop.sh Normal file
View File

@@ -0,0 +1,48 @@
PARSE_AND_LIST_OPTIONS_CALL_NOP='
fprintf (file, _("\
-z call-nop=PADDING Use PADDING as 1-byte NOP for branch\n"));
'
PARSE_AND_LIST_ARGS_CASE_Z_CALL_NOP='
else if (strncmp (optarg, "call-nop=", 9) == 0)
{
if (strcmp (optarg + 9, "prefix-addr") == 0)
{
link_info.call_nop_as_suffix = FALSE;
link_info.call_nop_byte = 0x67;
}
else if (strcmp (optarg + 9, "prefix-nop") == 0)
{
link_info.call_nop_as_suffix = FALSE;
link_info.call_nop_byte = 0x90;
}
else if (strcmp (optarg + 9, "suffix-nop") == 0)
{
link_info.call_nop_as_suffix = TRUE;
link_info.call_nop_byte = 0x90;
}
else if (strncmp (optarg + 9, "prefix-", 7) == 0)
{
char *end;
link_info.call_nop_byte = strtoul (optarg + 16 , &end, 0);
if (*end)
einfo (_("%P%F: invalid number for -z call-nop=prefix-: %s\n"),
optarg + 16);
link_info.call_nop_as_suffix = FALSE;
}
else if (strncmp (optarg + 9, "suffix-", 7) == 0)
{
char *end;
link_info.call_nop_byte = strtoul (optarg + 16, &end, 0);
if (*end)
einfo (_("%P%F: invalid number for -z call-nop=suffix-: %s\n"),
optarg + 16);
link_info.call_nop_as_suffix = TRUE;
}
else
einfo (_("%P%F: unsupported option: -z %s\n"), optarg);
}
'
PARSE_AND_LIST_OPTIONS="$PARSE_AND_LIST_OPTIONS $PARSE_AND_LIST_OPTIONS_CALL_NOP"
PARSE_AND_LIST_ARGS_CASE_Z="$PARSE_AND_LIST_ARGS_CASE_Z $PARSE_AND_LIST_ARGS_CASE_Z_CALL_NOP"
CALL_NOP_BYTE=0x67

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
ELFSIZE=32 ELFSIZE=32
OUTPUT_FORMAT="elf32-x86-64" OUTPUT_FORMAT="elf32-x86-64"

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386" OUTPUT_FORMAT="elf32-i386"
NO_RELA_RELOCS=yes NO_RELA_RELOCS=yes

View File

@@ -1,4 +1,5 @@
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386" OUTPUT_FORMAT="elf32-i386"
NO_RELA_RELOCS=yes NO_RELA_RELOCS=yes

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf_chaos SCRIPT_NAME=elf_chaos
OUTPUT_FORMAT="elf32-i386" OUTPUT_FORMAT="elf32-i386"
TEXT_START_ADDR=0x40000000 TEXT_START_ADDR=0x40000000

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386" OUTPUT_FORMAT="elf32-i386"
NO_RELA_RELOCS=yes NO_RELA_RELOCS=yes

View File

@@ -12,3 +12,4 @@ GENERATE_PIE_SCRIPT=yes
NO_SMALL_DATA=yes NO_SMALL_DATA=yes
. ${srcdir}/emulparams/vxworks.sh . ${srcdir}/emulparams/vxworks.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-iamcu" OUTPUT_FORMAT="elf32-iamcu"
NO_RELA_RELOCS=yes NO_RELA_RELOCS=yes

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
ELFSIZE=64 ELFSIZE=64
OUTPUT_FORMAT="elf64-k1om" OUTPUT_FORMAT="elf64-k1om"

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
ELFSIZE=64 ELFSIZE=64
OUTPUT_FORMAT="elf64-l1om" OUTPUT_FORMAT="elf64-l1om"

View File

@@ -1,5 +1,6 @@
. ${srcdir}/emulparams/plt_unwind.sh . ${srcdir}/emulparams/plt_unwind.sh
. ${srcdir}/emulparams/extern_protected_data.sh . ${srcdir}/emulparams/extern_protected_data.sh
. ${srcdir}/emulparams/call_nop.sh
SCRIPT_NAME=elf SCRIPT_NAME=elf
ELFSIZE=64 ELFSIZE=64
OUTPUT_FORMAT="elf64-x86-64" OUTPUT_FORMAT="elf64-x86-64"

View File

@@ -103,6 +103,7 @@ gld${EMULATION_NAME}_before_parse (void)
input_flags.dynamic = ${DYNAMIC_LINK-TRUE}; input_flags.dynamic = ${DYNAMIC_LINK-TRUE};
config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`; config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo TRUE ; else echo FALSE ; fi`;
config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`; config.separate_code = `if test "x${SEPARATE_CODE}" = xyes ; then echo TRUE ; else echo FALSE ; fi`;
`if test -n "$CALL_NOP_BYTE" ; then echo link_info.call_nop_byte = $CALL_NOP_BYTE; fi`;
} }
EOF EOF

View File

@@ -1199,6 +1199,20 @@ generated by compiler. Updates on protected data symbols by another
module aren't visible to the resulting shared library. Supported for module aren't visible to the resulting shared library. Supported for
i386 and x86-64. i386 and x86-64.
@item call-nop=prefix-addr
@itemx call-nop=prefix-nop
@itemx call-nop=suffix-nop
@itemx call-nop=prefix-@var{byte}
@itemx call-nop=suffix-@var{byte}
Specify the 1-byte @code{NOP} padding when transforming indirect call
to a locally defined function, foo, via its GOT slot.
@option{call-nop=prefix-addr} generates @code{0x67 call foo}.
@option{call-nop=prefix-nop} generates @code{0x90 call foo}.
@option{call-nop=suffix-nop} generates @code{call foo 0x90}.
@option{call-nop=prefix-@var{byte}} generates @code{@var{byte} call foo}.
@option{call-nop=suffix-@var{byte}} generates @code{call foo @var{byte}}.
Supported for i386 and x86_64.
@end table @end table
Other keywords are ignored for Solaris compatibility. Other keywords are ignored for Solaris compatibility.

View File

@@ -0,0 +1,17 @@
#as: --32
#ld: -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <bar>
[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
[ ]*[a-f0-9]+: e9 ([0-9a-f]{2} ){4} * jmp +[a-f0-9]+ <bar>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,15 @@
.text
.type bar, @function
bar:
ret
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
call *foo@GOT
call *bar@GOT
jmp *foo@GOT
jmp *bar@GOT

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,9 @@
.text
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
call *foo@GOT

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,8 @@
.text
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
call *foo@GOT

View File

@@ -0,0 +1,9 @@
.text
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
call *foo@GOT

View File

@@ -0,0 +1,13 @@
#source: call3.s
#as: --32
#ld: -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,13 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=prefix-addr
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=prefix-nop
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 90 nop
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * call +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=suffix-nop
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * call +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,13 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=prefix-0x67
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr16 call +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=prefix-0x90
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 90 nop
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * call +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=suffix-0x90
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * call +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,14 @@
#source: call3.s
#as: --32
#ld: -melf_i386 -z call-nop=suffix-144
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * call +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,20 @@
#...
[a-f0-9]+ <main>:
[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
[ ]*[a-f0-9]+: [ a-f0-9]+ addr16 call [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
[ ]*[a-f0-9]+: [ a-f0-9]+ call \*0x[a-f0-9]+
[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%eax
[ ]*[a-f0-9]+: ff d0 call \*%eax
[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
[ ]*[a-f0-9]+: ff d0 call \*%eax
[ ]*[a-f0-9]+: [ a-f0-9]+ mov *0x[a-f0-9]+,%eax
[ ]*[a-f0-9]+: ff d0 call \*%eax
[ ]*[a-f0-9]+: [ a-f0-9]+ lea *0x[a-f0-9]+,%ecx
[ ]*[a-f0-9]+: ff d1 call \*%ecx
[ ]*[a-f0-9]+: 83 ec 0c sub \$0xc,%esp
[ ]*[a-f0-9]+: 6a 00 push \$0x0
[ ]*[a-f0-9]+: 6a 00 push \$0x0
[ ]*[a-f0-9]+: [ a-f0-9]+ jmp [a-f0-9]+ <myexit>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,7 @@
foo
bar
plt
foo
bar
plt
foo

View File

@@ -0,0 +1,21 @@
.text
.globl main
.type main, @function
main:
subl $12, %esp
call *foo@GOT
call *bar@GOT
call *plt@GOT
movl foo@GOT, %eax
call *%eax
movl bar@GOT, %eax
call *%eax
movl plt@GOT, %eax
call *%eax
movl foo@GOT(%ebx), %ecx
call *%ecx
subl $12, %esp
pushl $0
pushl $0 # Push a dummy return address onto stack.
jmp *myexit@GOT
.size main, .-main

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
void
foo (void)
{
printf ("%s\n", __FUNCTION__);
}

View File

@@ -0,0 +1,7 @@
#include <stdlib.h>
void
myexit (int status)
{
exit (status);
}

View File

@@ -0,0 +1,54 @@
.globl bar
.type bar, @function
bar:
pushl %ebx
call __x86.get_pc_thunk.cx
addl $_GLOBAL_OFFSET_TABLE_, %ecx
subl $24, %esp
leal __FUNCTION__.1862@GOTOFF(%ecx), %eax
movl %eax, (%esp)
call *puts@GOT(%ecx)
addl $24, %esp
popl %ebx
ret
.size bar, .-bar
.globl plt
.type plt, @function
plt:
pushl %esi
pushl %ebx
call __x86.get_pc_thunk.bx
1:
addl $_GLOBAL_OFFSET_TABLE_, %ebx
subl $20, %esp
leal __FUNCTION__.1866@GOTOFF(%ebx), %esi
movl %esi, (%esp)
call *puts@GOT(%ebx)
addl $20, %esp
popl %ebx
popl %esi
ret
.section .rodata
.type __FUNCTION__.1866, @object
.size __FUNCTION__.1866, 4
__FUNCTION__.1866:
.string "plt"
.type __FUNCTION__.1862, @object
.size __FUNCTION__.1862, 4
__FUNCTION__.1862:
.string "bar"
.section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
.globl __x86.get_pc_thunk.bx
.hidden __x86.get_pc_thunk.bx
.type __x86.get_pc_thunk.bx, @function
__x86.get_pc_thunk.bx:
movl (%esp), %ebx
ret
.section .text.__x86.get_pc_thunk.cx,"axG",@progbits,__x86.get_pc_thunk.cx,comdat
.globl __x86.get_pc_thunk.cx
.hidden __x86.get_pc_thunk.cx
.type __x86.get_pc_thunk.cx, @function
__x86.get_pc_thunk.cx:
movl (%esp), %ecx
ret

View File

@@ -293,6 +293,28 @@ run_dump_test "lea1e"
run_dump_test "lea1f" run_dump_test "lea1f"
run_dump_test "mov1a" run_dump_test "mov1a"
run_dump_test "mov1b" run_dump_test "mov1b"
run_dump_test "branch1"
run_dump_test "call1"
run_dump_test "call2"
run_dump_test "call3a"
run_dump_test "call3b"
run_dump_test "call3c"
run_dump_test "call3d"
run_dump_test "call3e"
run_dump_test "call3f"
run_dump_test "call3g"
run_dump_test "call3h"
run_dump_test "jmp1"
run_dump_test "jmp2"
run_dump_test "load1"
run_dump_test "load1-nacl"
run_dump_test "load2"
run_dump_test "load3"
run_dump_test "load4a"
run_dump_test "load4b"
run_dump_test "load5a"
run_dump_test "load5b"
run_dump_test "load6"
if { !([istarget "i?86-*-linux*"] if { !([istarget "i?86-*-linux*"]
|| [istarget "i?86-*-gnu*"] || [istarget "i?86-*-gnu*"]
@@ -498,6 +520,22 @@ if { [isnative]
"" \ "" \
"pr19031.so" \ "pr19031.so" \
] \ ] \
[list \
"Build got1d.so" \
"-shared" \
"" \
{ got1d.S } \
"" \
"got1d.so" \
] \
[list \
"Build gotpc1" \
"tmpdir/got1d.so" \
"" \
{ got1a.S got1b.c got1c.c } \
{{objdump {-dw} got1.dd}} \
"got1" \
] \
] ]
run_ld_link_exec_tests [] [list \ run_ld_link_exec_tests [] [list \
@@ -568,6 +606,14 @@ if { [isnative]
"pr19031" \ "pr19031" \
"pr19031.out" \ "pr19031.out" \
] \ ] \
[list \
"Run got1" \
"tmpdir/got1d.so" \
"" \
{ got1a.S got1b.c got1c.c } \
"got1" \
"got1.out" \
] \
] ]
} }

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,9 @@
.text
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
jmp *foo@GOT

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,8 @@
.text
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
jmp *foo@GOT

View File

@@ -9,6 +9,6 @@
Disassembly of section .text: Disassembly of section .text:
#... #...
[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea -0x[a-f0-9]+\(%ecx\),%eax [ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
[ ]*[a-f0-9]+: 8d 81 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+\(%ecx\),%eax [ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
#pass #pass

View File

@@ -0,0 +1,59 @@
#source: load1.s
#as: --32
#ld: -melf_i386
#objdump: -dw --sym
#target: i?86-*-nacl* x86_64-*-nacl*
.*: +file format .*
SYMBOL TABLE:
#...
10030080 l O .data 0+1 bar
#...
10030081 g O .data 0+1 foo
#...
Disassembly of section .text:
0+20000 <_start>:
[ ]*[a-f0-9]+: 8d 05 80 00 03 10 lea 0x10030080,%eax
[ ]*[a-f0-9]+: 81 d0 80 00 03 10 adc \$0x10030080,%eax
[ ]*[a-f0-9]+: 81 c3 80 00 03 10 add \$0x10030080,%ebx
[ ]*[a-f0-9]+: 81 e1 80 00 03 10 and \$0x10030080,%ecx
[ ]*[a-f0-9]+: 81 fa 80 00 03 10 cmp \$0x10030080,%edx
[ ]*[a-f0-9]+: 81 cf 80 00 03 10 or \$0x10030080,%edi
[ ]*[a-f0-9]+: 81 de 80 00 03 10 sbb \$0x10030080,%esi
[ ]*[a-f0-9]+: 81 ed 80 00 03 10 sub \$0x10030080,%ebp
[ ]*[a-f0-9]+: 81 f4 80 00 03 10 xor \$0x10030080,%esp
[ ]*[a-f0-9]+: f7 c1 80 00 03 10 test \$0x10030080,%ecx
[ ]*[a-f0-9]+: 8d 05 80 00 03 10 lea 0x10030080,%eax
[ ]*[a-f0-9]+: 81 d0 80 00 03 10 adc \$0x10030080,%eax
[ ]*[a-f0-9]+: 81 c3 80 00 03 10 add \$0x10030080,%ebx
[ ]*[a-f0-9]+: 81 e1 80 00 03 10 and \$0x10030080,%ecx
[ ]*[a-f0-9]+: 81 fa 80 00 03 10 cmp \$0x10030080,%edx
[ ]*[a-f0-9]+: 81 cf 80 00 03 10 or \$0x10030080,%edi
[ ]*[a-f0-9]+: 81 de 80 00 03 10 sbb \$0x10030080,%esi
[ ]*[a-f0-9]+: 81 ed 80 00 03 10 sub \$0x10030080,%ebp
[ ]*[a-f0-9]+: 81 f4 80 00 03 10 xor \$0x10030080,%esp
[ ]*[a-f0-9]+: f7 c1 80 00 03 10 test \$0x10030080,%ecx
[ ]*[a-f0-9]+: 8d 05 81 00 03 10 lea 0x10030081,%eax
[ ]*[a-f0-9]+: 81 d0 81 00 03 10 adc \$0x10030081,%eax
[ ]*[a-f0-9]+: 81 c3 81 00 03 10 add \$0x10030081,%ebx
[ ]*[a-f0-9]+: 81 e1 81 00 03 10 and \$0x10030081,%ecx
[ ]*[a-f0-9]+: 81 fa 81 00 03 10 cmp \$0x10030081,%edx
[ ]*[a-f0-9]+: 81 cf 81 00 03 10 or \$0x10030081,%edi
[ ]*[a-f0-9]+: 81 de 81 00 03 10 sbb \$0x10030081,%esi
[ ]*[a-f0-9]+: 81 ed 81 00 03 10 sub \$0x10030081,%ebp
[ ]*[a-f0-9]+: 81 f4 81 00 03 10 xor \$0x10030081,%esp
[ ]*[a-f0-9]+: f7 c1 81 00 03 10 test \$0x10030081,%ecx
[ ]*[a-f0-9]+: 8d 05 81 00 03 10 lea 0x10030081,%eax
[ ]*[a-f0-9]+: 81 d0 81 00 03 10 adc \$0x10030081,%eax
[ ]*[a-f0-9]+: 81 c3 81 00 03 10 add \$0x10030081,%ebx
[ ]*[a-f0-9]+: 81 e1 81 00 03 10 and \$0x10030081,%ecx
[ ]*[a-f0-9]+: 81 fa 81 00 03 10 cmp \$0x10030081,%edx
[ ]*[a-f0-9]+: 81 cf 81 00 03 10 or \$0x10030081,%edi
[ ]*[a-f0-9]+: 81 de 81 00 03 10 sbb \$0x10030081,%esi
[ ]*[a-f0-9]+: 81 ed 81 00 03 10 sub \$0x10030081,%ebp
[ ]*[a-f0-9]+: 81 f4 81 00 03 10 xor \$0x10030081,%esp
[ ]*[a-f0-9]+: f7 c1 81 00 03 10 test \$0x10030081,%ecx
#pass

View File

@@ -0,0 +1,58 @@
#as: --32
#ld: -melf_i386
#objdump: -dw --sym
#notarget: i?86-*-nacl* x86_64-*-nacl*
.*: +file format .*
SYMBOL TABLE:
#...
0+8049170 l O .data 0+1 bar
#...
0+8049171 g O .data 0+1 foo
#...
Disassembly of section .text:
0+8048074 <_start>:
[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax
[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax
[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx
[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx
[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx
[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi
[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi
[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp
[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp
[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx
[ ]*[a-f0-9]+: 8d 05 70 91 04 08 lea 0x8049170,%eax
[ ]*[a-f0-9]+: 81 d0 70 91 04 08 adc \$0x8049170,%eax
[ ]*[a-f0-9]+: 81 c3 70 91 04 08 add \$0x8049170,%ebx
[ ]*[a-f0-9]+: 81 e1 70 91 04 08 and \$0x8049170,%ecx
[ ]*[a-f0-9]+: 81 fa 70 91 04 08 cmp \$0x8049170,%edx
[ ]*[a-f0-9]+: 81 cf 70 91 04 08 or \$0x8049170,%edi
[ ]*[a-f0-9]+: 81 de 70 91 04 08 sbb \$0x8049170,%esi
[ ]*[a-f0-9]+: 81 ed 70 91 04 08 sub \$0x8049170,%ebp
[ ]*[a-f0-9]+: 81 f4 70 91 04 08 xor \$0x8049170,%esp
[ ]*[a-f0-9]+: f7 c1 70 91 04 08 test \$0x8049170,%ecx
[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax
[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax
[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx
[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx
[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx
[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi
[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi
[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp
[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp
[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx
[ ]*[a-f0-9]+: 8d 05 71 91 04 08 lea 0x8049171,%eax
[ ]*[a-f0-9]+: 81 d0 71 91 04 08 adc \$0x8049171,%eax
[ ]*[a-f0-9]+: 81 c3 71 91 04 08 add \$0x8049171,%ebx
[ ]*[a-f0-9]+: 81 e1 71 91 04 08 and \$0x8049171,%ecx
[ ]*[a-f0-9]+: 81 fa 71 91 04 08 cmp \$0x8049171,%edx
[ ]*[a-f0-9]+: 81 cf 71 91 04 08 or \$0x8049171,%edi
[ ]*[a-f0-9]+: 81 de 71 91 04 08 sbb \$0x8049171,%esi
[ ]*[a-f0-9]+: 81 ed 71 91 04 08 sub \$0x8049171,%ebp
[ ]*[a-f0-9]+: 81 f4 71 91 04 08 xor \$0x8049171,%esp
[ ]*[a-f0-9]+: f7 c1 71 91 04 08 test \$0x8049171,%ecx
#pass

View File

@@ -0,0 +1,55 @@
.data
.type bar, @object
bar:
.byte 1
.size bar, .-bar
.globl foo
.type foo, @object
foo:
.byte 1
.size foo, .-foo
.text
.globl _start
.type _start, @function
_start:
movl bar@GOT(%ecx), %eax
adcl bar@GOT(%ecx), %eax
addl bar@GOT(%ecx), %ebx
andl bar@GOT(%ecx), %ecx
cmpl bar@GOT(%ecx), %edx
orl bar@GOT(%ecx), %edi
sbbl bar@GOT(%ecx), %esi
subl bar@GOT(%ecx), %ebp
xorl bar@GOT(%ecx), %esp
testl %ecx, bar@GOT(%ecx)
movl bar@GOT, %eax
adcl bar@GOT, %eax
addl bar@GOT, %ebx
andl bar@GOT, %ecx
cmpl bar@GOT, %edx
orl bar@GOT, %edi
sbbl bar@GOT, %esi
subl bar@GOT, %ebp
xorl bar@GOT, %esp
testl %ecx, bar@GOT
movl foo@GOT(%ecx), %eax
adcl foo@GOT(%ecx), %eax
addl foo@GOT(%ecx), %ebx
andl foo@GOT(%ecx), %ecx
cmpl foo@GOT(%ecx), %edx
orl foo@GOT(%ecx), %edi
sbbl foo@GOT(%ecx), %esi
subl foo@GOT(%ecx), %ebp
xorl foo@GOT(%ecx), %esp
testl %ecx, foo@GOT(%ecx)
movl foo@GOT, %eax
adcl foo@GOT, %eax
addl foo@GOT, %ebx
andl foo@GOT, %ecx
cmpl foo@GOT, %edx
orl foo@GOT, %edi
sbbl foo@GOT, %esi
subl foo@GOT, %ebp
xorl foo@GOT, %esp
testl %ecx, foo@GOT
.size _start, .-_start

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -melf_i386 -shared
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,8 @@
.data
.type foo, @object
foo:
.text
.globl _start
.type _start, @function
_start:
addl foo@GOT, %ebx

View File

@@ -0,0 +1,3 @@
#as: --32
#ld: -melf_i386 -shared
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,9 @@
.data
.globl foo
.type foo, @object
foo:
.text
.globl _start
.type _start, @function
_start:
addl foo@GOT, %ebx

View File

@@ -0,0 +1,9 @@
.text
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
movl foo@GOT, %eax

View File

@@ -0,0 +1,4 @@
#source: load4.s
#as: --32
#ld: -Bsymbolic -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,13 @@
#source: load4.s
#as: --32
#ld: -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
#pass

View File

@@ -0,0 +1,8 @@
.text
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
movl foo@GOT, %eax

View File

@@ -0,0 +1,4 @@
#source: load5.s
#as: --32
#ld: -Bsymbolic -shared -melf_i386
#error: direct GOT relocation R_386_GOT32X against `foo' without base register can not be used when making a shared object

View File

@@ -0,0 +1,13 @@
#source: load5.s
#as: --32
#ld: -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 8d 05 ([0-9a-f]{2} ){4} * lea 0x[a-f0-9]+,%eax
#pass

View File

@@ -0,0 +1,28 @@
#as: --32
#ld: -shared -melf_i386
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
[a-f0-9]+ <_start>:
[ ]*[a-f0-9]+: 13 81 f8 ff ff ff adc -0x8\(%ecx\),%eax
[ ]*[a-f0-9]+: 03 99 f8 ff ff ff add -0x8\(%ecx\),%ebx
[ ]*[a-f0-9]+: 23 89 f8 ff ff ff and -0x8\(%ecx\),%ecx
[ ]*[a-f0-9]+: 3b 91 f8 ff ff ff cmp -0x8\(%ecx\),%edx
[ ]*[a-f0-9]+: 0b b9 f8 ff ff ff or -0x8\(%ecx\),%edi
[ ]*[a-f0-9]+: 1b b1 f8 ff ff ff sbb -0x8\(%ecx\),%esi
[ ]*[a-f0-9]+: 2b a9 f8 ff ff ff sub -0x8\(%ecx\),%ebp
[ ]*[a-f0-9]+: 33 a1 f8 ff ff ff xor -0x8\(%ecx\),%esp
[ ]*[a-f0-9]+: 85 89 f8 ff ff ff test %ecx,-0x8\(%ecx\)
[ ]*[a-f0-9]+: 13 81 fc ff ff ff adc -0x4\(%ecx\),%eax
[ ]*[a-f0-9]+: 03 99 fc ff ff ff add -0x4\(%ecx\),%ebx
[ ]*[a-f0-9]+: 23 89 fc ff ff ff and -0x4\(%ecx\),%ecx
[ ]*[a-f0-9]+: 3b 91 fc ff ff ff cmp -0x4\(%ecx\),%edx
[ ]*[a-f0-9]+: 0b b9 fc ff ff ff or -0x4\(%ecx\),%edi
[ ]*[a-f0-9]+: 1b b1 fc ff ff ff sbb -0x4\(%ecx\),%esi
[ ]*[a-f0-9]+: 2b a9 fc ff ff ff sub -0x4\(%ecx\),%ebp
[ ]*[a-f0-9]+: 33 a1 fc ff ff ff xor -0x4\(%ecx\),%esp
[ ]*[a-f0-9]+: 85 89 fc ff ff ff test %ecx,-0x4\(%ecx\)
#pass

View File

@@ -0,0 +1,33 @@
.data
.type bar, @object
bar:
.byte 1
.size bar, .-bar
.globl foo
.type foo, @object
foo:
.byte 1
.size foo, .-foo
.text
.globl _start
.type _start, @function
_start:
adcl bar@GOT(%ecx), %eax
addl bar@GOT(%ecx), %ebx
andl bar@GOT(%ecx), %ecx
cmpl bar@GOT(%ecx), %edx
orl bar@GOT(%ecx), %edi
sbbl bar@GOT(%ecx), %esi
subl bar@GOT(%ecx), %ebp
xorl bar@GOT(%ecx), %esp
testl %ecx, bar@GOT(%ecx)
adcl foo@GOT(%ecx), %eax
addl foo@GOT(%ecx), %ebx
andl foo@GOT(%ecx), %ecx
cmpl foo@GOT(%ecx), %edx
orl foo@GOT(%ecx), %edi
sbbl foo@GOT(%ecx), %esi
subl foo@GOT(%ecx), %ebp
xorl foo@GOT(%ecx), %esp
testl %ecx, foo@GOT(%ecx)
.size _start, .-_start

View File

@@ -1,3 +1,3 @@
#... #...
[0-9a-f ]+R_386_GOT32 +0+ +bar [0-9a-f ]+R_386_GOT32X +0+ +bar
#pass #pass

View File

@@ -1,5 +1,5 @@
#... #...
[0-9a-f ]+R_386_GOT32 +0+ +bar [0-9a-f ]+R_386_GOT32X +0+ +bar
#... #...
[0-9a-f ]+R_386_PLT32 +0+ +bar [0-9a-f ]+R_386_PLT32 +0+ +bar
#pass #pass

View File

@@ -1,5 +1,5 @@
#... #...
[0-9a-f ]+R_386_GOT32 +0+ +foo [0-9a-f ]+R_386_GOT32X +0+ +foo
#... #...
[0-9a-f ]+R_386_PLT32 +0+ +foo [0-9a-f ]+R_386_PLT32 +0+ +foo
#pass #pass

View File

@@ -7,4 +7,4 @@
Relocation section '.rela.text' at .* Relocation section '.rela.text' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.* [ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_PLT32[ ]+foo\(\)[ ]+foo - 4 [0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_PLT32[ ]+foo\(\)[ ]+foo - 4
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_GOTPCREL[ ]+foo\(\)[ ]+foo - 4 [0-9a-f]+[ ]+[0-9a-f]+[ ]+R_X86_64_REX_GOTPCRELX[ ]+foo\(\)[ ]+foo - 4

View File

@@ -0,0 +1,9 @@
.text
.globl foo
.type foo, @function
foo:
ret
.globl _start
.type _start, @function
_start:
call *foo@GOTPCREL(%rip)

View File

@@ -0,0 +1,13 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr32 callq +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,13 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=prefix-addr
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr32 callq +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=prefix-nop
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 90 nop
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=suffix-nop
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,13 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=prefix-0x67
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 67 e8 ([0-9a-f]{2} ){4} * addr32 callq +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=prefix-0x90
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: 90 nop
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=suffix-0x90
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --64
#ld: -melf_x86_64 -z call-nop=suffix-144
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,14 @@
#source: call1.s
#as: --x32
#ld: -melf32_x86_64 -z call-nop=suffix-0x90
#objdump: -dw
.*: +file format .*
Disassembly of section .text:
#...
[ ]*[a-f0-9]+: e8 ([0-9a-f]{2} ){4} * callq +[a-f0-9]+ <foo>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,17 @@
#...
[a-f0-9]+ <main>:
[ ]*[a-f0-9]+: 48 83 ec 08 sub \$0x8,%rsp
[ ]*[a-f0-9]+: [ a-f0-9]+ addr32 callq [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: [ a-f0-9]+ callq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: [ a-f0-9]+ callq \*0x[a-f0-9]+\(%rip\) # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: [ a-f0-9]+ lea 0x[a-f0-9]+\(%rip\),%rax # [a-f0-9]+ <foo>
[ ]*[a-f0-9]+: ff d0 callq \*%rax
[ ]*[a-f0-9]+: [ a-f0-9]+ mov 0x[a-f0-9]+\(%rip\),%rcx # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: ff d1 callq \*%rcx
[ ]*[a-f0-9]+: [ a-f0-9]+ mov 0x[a-f0-9]+\(%rip\),%rdx # [a-f0-9]+ <_DYNAMIC\+0x[a-f0-9]+>
[ ]*[a-f0-9]+: ff d2 callq \*%rdx
[ ]*[a-f0-9]+: 31 ff xor %edi,%edi
[ ]*[a-f0-9]+: 48 83 c4 08 add \$0x8,%rsp
[ ]*[a-f0-9]+: [ a-f0-9]+ jmpq [a-f0-9]+ <myexit>
[ ]*[a-f0-9]+: 90 nop
#pass

View File

@@ -0,0 +1,8 @@
foo
bar
plt
plt
foo
bar
plt
plt

View File

@@ -0,0 +1,18 @@
.text
.globl main
.type main, @function
main:
subq $8, %rsp
call *foo@GOTPCREL(%rip)
call *bar@GOTPCREL(%rip)
call *plt@GOTPCREL(%rip)
movq foo@GOTPCREL(%rip), %rax
call *%rax
movq bar@GOTPCREL(%rip), %rcx
call *%rcx
movq plt@GOTPCREL(%rip), %rdx
call *%rdx
xorl %edi, %edi
addq $8, %rsp
jmp *myexit@GOTPCREL(%rip)
.size main, .-main

View File

@@ -0,0 +1,7 @@
#include <stdio.h>
void
foo (void)
{
printf ("%s\n", __FUNCTION__);
}

View File

@@ -0,0 +1,7 @@
#include <stdlib.h>
void
myexit (int status)
{
exit (status);
}

View File

@@ -0,0 +1,26 @@
.text
.globl bar
.type bar, @function
bar:
leaq __FUNCTION__.2215(%rip), %rdi
jmp *puts@GOTPCREL(%rip)
.size bar, .-bar
.globl plt
.type plt, @function
plt:
leaq __FUNCTION__.2219(%rip), %rdi
subq $8, %rsp
call *puts@GOTPCREL(%rip)
leaq __FUNCTION__.2219(%rip), %rdi
addq $8, %rsp
jmp *puts@GOTPCREL(%rip)
.size plt, .-plt
.section .rodata
.type __FUNCTION__.2219, @object
.size __FUNCTION__.2219, 4
__FUNCTION__.2219:
.string "plt"
.type __FUNCTION__.2215, @object
.size __FUNCTION__.2215, 4
__FUNCTION__.2215:
.string "bar"

Some files were not shown because too many files have changed in this diff Show More