Patch by matz@suse.de:

bfd/ChangeLog:
	* reloc.c: Add BFD_RELOC_X86_64_GOT64, BFD_RELOC_X86_64_GOTPCREL64,
	BFD_RELOC_X86_64_GOTPC64, BFD_RELOC_X86_64_GOTPLT64,
	BFD_RELOC_X86_64_PLTOFF64.
	* bfd-in2.h: Regenerated.
	* libbfd.h: Regenerated.
	* elf64-x86-64.c (x86_64_elf_howto_table): Correct comment.
	Add howtos for above relocs.
	(x86_64_reloc_map): Add mappings for new relocs.
	(elf64_x86_64_check_relocs): R_X86_64_GOT64, R_X86_64_GOTPCREL64,
	R_X86_64_GOTPLT64 need a got entry.  R_X86_64_GOTPLT64 also a PLT
	entry.  R_X86_64_GOTPC64 needs a .got section.  R_X86_64_PLTOFF64
	needs a PLT entry.
	(elf64_x86_64_gc_sweep_hook): Reflect changes from
	elf64_x86_64_check_relocs for the new relocs.
	(elf64_x86_64_relocate_section): Handle new relocs.

gas/ChangeLog:
	* config/tc-i386.c (type_names): Correct placement of 'static'.
	(reloc): Map some more relocs to their 64 bit counterpart when
	size is 8.
	(output_insn): Work around breakage if DEBUG386 is defined.
	(output_disp): A BFD_RELOC_64 with GOT_symbol as operand also
	needs to be mapped to BFD_RELOC_X86_64_GOTPC64 or
	BFD_RELOC_X86_64_GOTPC32.  Also x86-64 handles pcrel addressing
	different from i386.
	(output_imm): Ditto.
	(lex_got): Recognize @PLTOFF and @GOTPLT.  Make @GOT accept also
	Imm64.
	(md_convert_frag): Jumps can now be larger than 2GB away, error
	out in that case.
	(tc_gen_reloc): New relocs are passed through.  BFD_RELOC_64
	and BFD_RELOC_64_PCREL are mapped to BFD_RELOC_X86_64_GOTPC64.

gas/testsuite/ChangeLog:
	* gas/i386/reloc64.s: Accept 64-bit forms.
	* gas/i386/reloc64.d: Adjust.
	* gas/i386/reloc64.l: Adjust.

include/ChangeLog:
	* elf/x86-64.h: Add the new relocations with their official
	numbers.
This commit is contained in:
Andreas Jaeger 2006-03-23 08:23:09 +00:00
parent c5f44798e0
commit 7b81dfbbf9
10 changed files with 208 additions and 35 deletions

View File

@ -2707,6 +2707,11 @@ in the instruction. */
BFD_RELOC_X86_64_TPOFF32, BFD_RELOC_X86_64_TPOFF32,
BFD_RELOC_X86_64_GOTOFF64, BFD_RELOC_X86_64_GOTOFF64,
BFD_RELOC_X86_64_GOTPC32, BFD_RELOC_X86_64_GOTPC32,
BFD_RELOC_X86_64_GOT64,
BFD_RELOC_X86_64_GOTPCREL64,
BFD_RELOC_X86_64_GOTPC64,
BFD_RELOC_X86_64_GOTPLT64,
BFD_RELOC_X86_64_PLTOFF64,
BFD_RELOC_X86_64_GOTPC32_TLSDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC,
BFD_RELOC_X86_64_TLSDESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL,
BFD_RELOC_X86_64_TLSDESC, BFD_RELOC_X86_64_TLSDESC,

View File

@ -31,8 +31,8 @@
#define MINUS_ONE (~ (bfd_vma) 0) #define MINUS_ONE (~ (bfd_vma) 0)
/* The relocation "howto" table. Order of fields: /* The relocation "howto" table. Order of fields:
type, size, bitsize, pc_relative, complain_on_overflow, type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset. */ special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */
static reloc_howto_type x86_64_elf_howto_table[] = static reloc_howto_type x86_64_elf_howto_table[] =
{ {
HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont, HOWTO(R_X86_64_NONE, 0, 0, 0, FALSE, 0, complain_overflow_dont,
@ -112,11 +112,21 @@ static reloc_howto_type x86_64_elf_howto_table[] =
HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed, HOWTO(R_X86_64_GOTPC32, 0, 2, 32, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_GOTPC32", bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
FALSE, 0xffffffff, 0xffffffff, TRUE), FALSE, 0xffffffff, 0xffffffff, TRUE),
EMPTY_HOWTO (27), HOWTO(R_X86_64_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
EMPTY_HOWTO (28), bfd_elf_generic_reloc, "R_X86_64_GOT64", FALSE, MINUS_ONE, MINUS_ONE,
EMPTY_HOWTO (29), FALSE),
EMPTY_HOWTO (30), HOWTO(R_X86_64_GOTPCREL64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
EMPTY_HOWTO (31), bfd_elf_generic_reloc, "R_X86_64_GOTPCREL64", FALSE, MINUS_ONE,
MINUS_ONE, TRUE),
HOWTO(R_X86_64_GOTPC64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_GOTPC64",
FALSE, MINUS_ONE, MINUS_ONE, TRUE),
HOWTO(R_X86_64_GOTPLT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_GOTPLT64", FALSE, MINUS_ONE,
MINUS_ONE, FALSE),
HOWTO(R_X86_64_PLTOFF64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
bfd_elf_generic_reloc, "R_X86_64_PLTOFF64", FALSE, MINUS_ONE,
MINUS_ONE, FALSE),
EMPTY_HOWTO (32), EMPTY_HOWTO (32),
EMPTY_HOWTO (33), EMPTY_HOWTO (33),
HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0, HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
@ -185,6 +195,11 @@ static const struct elf_reloc_map x86_64_reloc_map[] =
{ BFD_RELOC_64_PCREL, R_X86_64_PC64, }, { BFD_RELOC_64_PCREL, R_X86_64_PC64, },
{ BFD_RELOC_X86_64_GOTOFF64, R_X86_64_GOTOFF64, }, { BFD_RELOC_X86_64_GOTOFF64, R_X86_64_GOTOFF64, },
{ BFD_RELOC_X86_64_GOTPC32, R_X86_64_GOTPC32, }, { BFD_RELOC_X86_64_GOTPC32, R_X86_64_GOTPC32, },
{ BFD_RELOC_X86_64_GOT64, R_X86_64_GOT64, },
{ BFD_RELOC_X86_64_GOTPCREL64,R_X86_64_GOTPCREL64, },
{ BFD_RELOC_X86_64_GOTPC64, R_X86_64_GOTPC64, },
{ BFD_RELOC_X86_64_GOTPLT64, R_X86_64_GOTPLT64, },
{ BFD_RELOC_X86_64_PLTOFF64, R_X86_64_PLTOFF64, },
{ BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, }, { BFD_RELOC_X86_64_GOTPC32_TLSDESC, R_X86_64_GOTPC32_TLSDESC, },
{ 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, },
@ -777,6 +792,9 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
case R_X86_64_GOT32: case R_X86_64_GOT32:
case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL:
case R_X86_64_TLSGD: case R_X86_64_TLSGD:
case R_X86_64_GOT64:
case R_X86_64_GOTPCREL64:
case R_X86_64_GOTPLT64:
case R_X86_64_GOTPC32_TLSDESC: case R_X86_64_GOTPC32_TLSDESC:
case R_X86_64_TLSDESC_CALL: case R_X86_64_TLSDESC_CALL:
/* This symbol requires a global offset table entry. */ /* This symbol requires a global offset table entry. */
@ -795,6 +813,14 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
if (h != NULL) if (h != NULL)
{ {
if (r_type == R_X86_64_GOTPLT64)
{
/* This relocation indicates that we also need
a PLT entry, as this is a function. We don't need
a PLT entry for local symbols. */
h->needs_plt = 1;
h->plt.refcount += 1;
}
h->got.refcount += 1; h->got.refcount += 1;
old_tls_type = elf64_x86_64_hash_entry (h)->tls_type; old_tls_type = elf64_x86_64_hash_entry (h)->tls_type;
} }
@ -858,6 +884,7 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
case R_X86_64_GOTOFF64: case R_X86_64_GOTOFF64:
case R_X86_64_GOTPC32: case R_X86_64_GOTPC32:
case R_X86_64_GOTPC64:
create_got: create_got:
if (htab->sgot == NULL) if (htab->sgot == NULL)
{ {
@ -885,6 +912,16 @@ elf64_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, asection *sec,
h->plt.refcount += 1; h->plt.refcount += 1;
break; break;
case R_X86_64_PLTOFF64:
/* This tries to form the 'address' of a function relative
to GOT. For global symbols we need a PLT entry. */
if (h != NULL)
{
h->needs_plt = 1;
h->plt.refcount += 1;
}
goto create_got;
case R_X86_64_8: case R_X86_64_8:
case R_X86_64_16: case R_X86_64_16:
case R_X86_64_32: case R_X86_64_32:
@ -1189,8 +1226,13 @@ elf64_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_GOT64:
case R_X86_64_GOTPCREL64:
case R_X86_64_GOTPLT64:
if (h != NULL) if (h != NULL)
{ {
if (r_type == R_X86_64_GOTPLT64 && h->plt.refcount > 0)
h->plt.refcount -= 1;
if (h->got.refcount > 0) if (h->got.refcount > 0)
h->got.refcount -= 1; h->got.refcount -= 1;
} }
@ -1215,6 +1257,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
/* Fall thru */ /* Fall thru */
case R_X86_64_PLT32: case R_X86_64_PLT32:
case R_X86_64_PLTOFF64:
if (h != NULL) if (h != NULL)
{ {
if (h->plt.refcount > 0) if (h->plt.refcount > 0)
@ -2096,11 +2139,23 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
copied into the output file to be resolved at run time. */ copied into the output file to be resolved at run time. */
switch (r_type) switch (r_type)
{ {
asection *base_got;
case R_X86_64_GOT32: case R_X86_64_GOT32:
case R_X86_64_GOT64:
/* 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:
/* Use global offset table as symbol value. */ case R_X86_64_GOTPCREL64:
/* Use global offset table entry as symbol value. */
case R_X86_64_GOTPLT64:
/* This is the same as GOT64 for relocation purposes, but
indicates the existence of a PLT entry. The difficulty is,
that we must calculate the GOT slot offset from the PLT
offset, if this symbol got a PLT entry (it was global).
Additionally if it's computed from the PLT entry, then that
GOT offset is relative to .got.plt, not to .got. */
base_got = htab->sgot;
if (htab->sgot == NULL) if (htab->sgot == NULL)
abort (); abort ();
@ -2109,6 +2164,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
bfd_boolean dyn; bfd_boolean dyn;
off = h->got.offset; off = h->got.offset;
if (h->needs_plt
&& h->plt.offset != (bfd_vma)-1
&& off == (bfd_vma)-1)
{
/* We can't use h->got.offset here to save
state, or even just remember the offset, as
finish_dynamic_symbol would use that as offset into
.got. */
bfd_vma plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1;
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = htab->sgotplt;
}
dyn = htab->elf.dynamic_sections_created; dyn = htab->elf.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h) if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info->shared, h)
@ -2133,7 +2201,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
else else
{ {
bfd_put_64 (output_bfd, relocation, bfd_put_64 (output_bfd, relocation,
htab->sgot->contents + off); base_got->contents + off);
/* Note that this is harmless for the GOTPLT64 case,
as -1 | 1 still is -1. */
h->got.offset |= 1; h->got.offset |= 1;
} }
} }
@ -2155,7 +2225,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
else else
{ {
bfd_put_64 (output_bfd, relocation, bfd_put_64 (output_bfd, relocation,
htab->sgot->contents + off); base_got->contents + off);
if (info->shared) if (info->shared)
{ {
@ -2169,8 +2239,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
if (s == NULL) if (s == NULL)
abort (); abort ();
outrel.r_offset = (htab->sgot->output_section->vma outrel.r_offset = (base_got->output_section->vma
+ htab->sgot->output_offset + base_got->output_offset
+ off); + off);
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE); outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
outrel.r_addend = relocation; outrel.r_addend = relocation;
@ -2186,9 +2256,9 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
if (off >= (bfd_vma) -2) if (off >= (bfd_vma) -2)
abort (); abort ();
relocation = htab->sgot->output_section->vma relocation = base_got->output_section->vma
+ htab->sgot->output_offset + off; + base_got->output_offset + off;
if (r_type != R_X86_64_GOTPCREL) if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64)
relocation -= htab->sgotplt->output_section->vma relocation -= htab->sgotplt->output_section->vma
- htab->sgotplt->output_offset; - htab->sgotplt->output_offset;
@ -2224,12 +2294,31 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
break; break;
case R_X86_64_GOTPC32: case R_X86_64_GOTPC32:
case R_X86_64_GOTPC64:
/* Use global offset table as symbol value. */ /* Use global offset table as symbol value. */
relocation = htab->sgotplt->output_section->vma relocation = htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset; + htab->sgotplt->output_offset;
unresolved_reloc = FALSE; unresolved_reloc = FALSE;
break; break;
case R_X86_64_PLTOFF64:
/* Relocation is PLT entry relative to GOT. For local
symbols it's the symbol itself relative to GOT. */
if (h != NULL
/* See PLT32 handling. */
&& h->plt.offset != (bfd_vma) -1
&& htab->splt != NULL)
{
relocation = (htab->splt->output_section->vma
+ htab->splt->output_offset
+ h->plt.offset);
unresolved_reloc = FALSE;
}
relocation -= htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset;
break;
case R_X86_64_PLT32: case R_X86_64_PLT32:
/* Relocation is to the entry for this symbol in the /* Relocation is to the entry for this symbol in the
procedure linkage table. */ procedure linkage table. */

View File

@ -7,7 +7,7 @@
(This include file is not for users of the library.) (This include file is not for users of the library.)
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc. Free Software Foundation, Inc.
Written by Cygnus Support. Written by Cygnus Support.
@ -1065,6 +1065,11 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_X86_64_TPOFF32", "BFD_RELOC_X86_64_TPOFF32",
"BFD_RELOC_X86_64_GOTOFF64", "BFD_RELOC_X86_64_GOTOFF64",
"BFD_RELOC_X86_64_GOTPC32", "BFD_RELOC_X86_64_GOTPC32",
"BFD_RELOC_X86_64_GOT64",
"BFD_RELOC_X86_64_GOTPCREL64",
"BFD_RELOC_X86_64_GOTPC64",
"BFD_RELOC_X86_64_GOTPLT64",
"BFD_RELOC_X86_64_PLTOFF64",
"BFD_RELOC_X86_64_GOTPC32_TLSDESC", "BFD_RELOC_X86_64_GOTPC32_TLSDESC",
"BFD_RELOC_X86_64_TLSDESC_CALL", "BFD_RELOC_X86_64_TLSDESC_CALL",
"BFD_RELOC_X86_64_TLSDESC", "BFD_RELOC_X86_64_TLSDESC",

View File

@ -4,7 +4,7 @@
/* BFD COFF object file private structure. /* BFD COFF object file private structure.
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc. Free Software Foundation, Inc.
Written by Cygnus Support. Written by Cygnus Support.

View File

@ -2351,6 +2351,16 @@ ENUMX
BFD_RELOC_X86_64_GOTOFF64 BFD_RELOC_X86_64_GOTOFF64
ENUMX ENUMX
BFD_RELOC_X86_64_GOTPC32 BFD_RELOC_X86_64_GOTPC32
ENUMX
BFD_RELOC_X86_64_GOT64
ENUMX
BFD_RELOC_X86_64_GOTPCREL64
ENUMX
BFD_RELOC_X86_64_GOTPC64
ENUMX
BFD_RELOC_X86_64_GOTPLT64
ENUMX
BFD_RELOC_X86_64_PLTOFF64
ENUMX ENUMX
BFD_RELOC_X86_64_GOTPC32_TLSDESC BFD_RELOC_X86_64_GOTPC32_TLSDESC
ENUMX ENUMX

View File

@ -1169,13 +1169,12 @@ ps (s)
segment_name (S_GET_SEGMENT (s))); segment_name (S_GET_SEGMENT (s)));
} }
struct type_name static struct type_name
{ {
unsigned int mask; unsigned int mask;
char *tname; char *tname;
} }
const type_names[] =
static const type_names[] =
{ {
{ Reg8, "r8" }, { Reg8, "r8" },
{ Reg16, "r16" }, { Reg16, "r16" },
@ -1238,6 +1237,18 @@ reloc (unsigned int size,
if (size == 8) if (size == 8)
switch (other) switch (other)
{ {
case BFD_RELOC_X86_64_GOT32:
return BFD_RELOC_X86_64_GOT64;
break;
case BFD_RELOC_X86_64_PLTOFF64:
return BFD_RELOC_X86_64_PLTOFF64;
break;
case BFD_RELOC_X86_64_GOTPC32:
other = BFD_RELOC_X86_64_GOTPC64;
break;
case BFD_RELOC_X86_64_GOTPCREL:
other = BFD_RELOC_X86_64_GOTPCREL64;
break;
case BFD_RELOC_X86_64_TPOFF32: case BFD_RELOC_X86_64_TPOFF32:
other = BFD_RELOC_X86_64_TPOFF64; other = BFD_RELOC_X86_64_TPOFF64;
break; break;
@ -3569,7 +3580,7 @@ check_prefix:
#ifdef DEBUG386 #ifdef DEBUG386
if (flag_debug) if (flag_debug)
{ {
pi (line, &i); pi ("" /*line*/, &i);
} }
#endif /* DEBUG386 */ #endif /* DEBUG386 */
} }
@ -3654,7 +3665,9 @@ output_disp (insn_start_frag, insn_start_off)
if (GOT_symbol if (GOT_symbol
&& GOT_symbol == i.op[n].disps->X_add_symbol && GOT_symbol == i.op[n].disps->X_add_symbol
&& (((reloc_type == BFD_RELOC_32 && (((reloc_type == BFD_RELOC_32
|| reloc_type == BFD_RELOC_X86_64_32S) || reloc_type == BFD_RELOC_X86_64_32S
|| (reloc_type == BFD_RELOC_64
&& object_64bit))
&& (i.op[n].disps->X_op == O_symbol && (i.op[n].disps->X_op == O_symbol
|| (i.op[n].disps->X_op == O_add || (i.op[n].disps->X_op == O_add
&& ((symbol_get_value_expression && ((symbol_get_value_expression
@ -3678,10 +3691,17 @@ output_disp (insn_start_frag, insn_start_off)
} }
if (!object_64bit) if (!object_64bit)
reloc_type = BFD_RELOC_386_GOTPC; {
reloc_type = BFD_RELOC_386_GOTPC;
i.op[n].imms->X_add_number += add;
}
else if (reloc_type == BFD_RELOC_64)
reloc_type = BFD_RELOC_X86_64_GOTPC64;
else else
/* Don't do the adjustment for x86-64, as there
the pcrel addressing is relative to the _next_
insn, and that is taken care of in other code. */
reloc_type = BFD_RELOC_X86_64_GOTPC32; reloc_type = BFD_RELOC_X86_64_GOTPC32;
i.op[n].disps->X_add_number += add;
} }
fix_new_exp (frag_now, p - frag_now->fr_literal, size, fix_new_exp (frag_now, p - frag_now->fr_literal, size,
i.op[n].disps, pcrel, reloc_type); i.op[n].disps, pcrel, reloc_type);
@ -3790,7 +3810,8 @@ output_imm (insn_start_frag, insn_start_off)
* confusing to do it this way. */ * confusing to do it this way. */
if ((reloc_type == BFD_RELOC_32 if ((reloc_type == BFD_RELOC_32
|| reloc_type == BFD_RELOC_X86_64_32S) || reloc_type == BFD_RELOC_X86_64_32S
|| reloc_type == BFD_RELOC_64)
&& GOT_symbol && GOT_symbol
&& GOT_symbol == i.op[n].imms->X_add_symbol && GOT_symbol == i.op[n].imms->X_add_symbol
&& (i.op[n].imms->X_op == O_symbol && (i.op[n].imms->X_op == O_symbol
@ -3816,8 +3837,10 @@ output_imm (insn_start_frag, insn_start_off)
if (!object_64bit) if (!object_64bit)
reloc_type = BFD_RELOC_386_GOTPC; reloc_type = BFD_RELOC_386_GOTPC;
else else if (size == 4)
reloc_type = BFD_RELOC_X86_64_GOTPC32; reloc_type = BFD_RELOC_X86_64_GOTPC32;
else if (size == 8)
reloc_type = BFD_RELOC_X86_64_GOTPC64;
i.op[n].imms->X_add_number += add; i.op[n].imms->X_add_number += add;
} }
fix_new_exp (frag_now, p - frag_now->fr_literal, size, fix_new_exp (frag_now, p - frag_now->fr_literal, size,
@ -3870,12 +3893,19 @@ lex_got (enum bfd_reloc_code_real *reloc,
int *adjust, int *adjust,
unsigned int *types) unsigned int *types)
{ {
/* Some of the relocations depend on the size of what field is to
be relocated. But in our callers i386_immediate and i386_displacement
we don't yet know the operand size (this will be set by insn
matching). Hence we record the word32 relocation here,
and adjust the reloc according to the real size in reloc(). */
static const struct { static const struct {
const char *str; const char *str;
const enum bfd_reloc_code_real rel[2]; const enum bfd_reloc_code_real rel[2];
const unsigned int types64; const unsigned int types64;
} gotrel[] = { } gotrel[] = {
{ "PLTOFF", { 0, BFD_RELOC_X86_64_PLTOFF64 }, Imm64 },
{ "PLT", { BFD_RELOC_386_PLT32, BFD_RELOC_X86_64_PLT32 }, Imm32|Imm32S|Disp32 }, { "PLT", { BFD_RELOC_386_PLT32, BFD_RELOC_X86_64_PLT32 }, Imm32|Imm32S|Disp32 },
{ "GOTPLT", { 0, BFD_RELOC_X86_64_GOTPLT64 }, Imm64|Disp64 },
{ "GOTOFF", { BFD_RELOC_386_GOTOFF, BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 }, { "GOTOFF", { BFD_RELOC_386_GOTOFF, BFD_RELOC_X86_64_GOTOFF64 }, Imm64|Disp64 },
{ "GOTPCREL", { 0, BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 }, { "GOTPCREL", { 0, BFD_RELOC_X86_64_GOTPCREL }, Imm32|Imm32S|Disp32 },
{ "TLSGD", { BFD_RELOC_386_TLS_GD, BFD_RELOC_X86_64_TLSGD }, Imm32|Imm32S|Disp32 }, { "TLSGD", { BFD_RELOC_386_TLS_GD, BFD_RELOC_X86_64_TLSGD }, Imm32|Imm32S|Disp32 },
@ -3887,7 +3917,7 @@ lex_got (enum bfd_reloc_code_real *reloc,
{ "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 }, { "DTPOFF", { BFD_RELOC_386_TLS_LDO_32, BFD_RELOC_X86_64_DTPOFF32 }, Imm32|Imm32S|Imm64|Disp32|Disp64 },
{ "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0 }, 0 }, { "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 0 }, 0 },
{ "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0 }, 0 }, { "INDNTPOFF",{ BFD_RELOC_386_TLS_IE, 0 }, 0 },
{ "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32 }, { "GOT", { BFD_RELOC_386_GOT32, BFD_RELOC_X86_64_GOT32 }, Imm32|Imm32S|Disp32|Imm64 },
{ "TLSDESC", { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 }, { "TLSDESC", { BFD_RELOC_386_TLS_GOTDESC, BFD_RELOC_X86_64_GOTPC32_TLSDESC }, Imm32|Imm32S|Disp32 },
{ "TLSCALL", { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 } { "TLSCALL", { BFD_RELOC_386_TLS_DESC_CALL, BFD_RELOC_X86_64_TLSDESC_CALL }, Imm32|Imm32S|Disp32 }
}; };
@ -4947,6 +4977,20 @@ md_convert_frag (abfd, sec, fragP)
} }
} }
/* If size if less then four we are sure that the operand fits,
but if it's 4, then it could be that the displacement is larger
then -/+ 2GB. */
if (DISP_SIZE_FROM_RELAX_STATE (fragP->fr_subtype) == 4
&& object_64bit
&& ((addressT) (displacement_from_opcode_start - extension
+ ((addressT) 1 << 31))
> (((addressT) 2 << 31) - 1)))
{
as_bad_where (fragP->fr_file, fragP->fr_line,
_("jump target out of range"));
/* Make us emit 0. */
displacement_from_opcode_start = extension;
}
/* Now put displacement after opcode. */ /* Now put displacement after opcode. */
md_number_to_chars ((char *) where_to_put_displacement, md_number_to_chars ((char *) where_to_put_displacement,
(valueT) (displacement_from_opcode_start - extension), (valueT) (displacement_from_opcode_start - extension),
@ -5708,6 +5752,11 @@ tc_gen_reloc (section, fixp)
case BFD_RELOC_X86_64_TPOFF64: case BFD_RELOC_X86_64_TPOFF64:
case BFD_RELOC_X86_64_GOTOFF64: case BFD_RELOC_X86_64_GOTOFF64:
case BFD_RELOC_X86_64_GOTPC32: case BFD_RELOC_X86_64_GOTPC32:
case BFD_RELOC_X86_64_GOT64:
case BFD_RELOC_X86_64_GOTPCREL64:
case BFD_RELOC_X86_64_GOTPC64:
case BFD_RELOC_X86_64_GOTPLT64:
case BFD_RELOC_X86_64_PLTOFF64:
case BFD_RELOC_X86_64_GOTPC32_TLSDESC: case BFD_RELOC_X86_64_GOTPC32_TLSDESC:
case BFD_RELOC_X86_64_TLSDESC_CALL: case BFD_RELOC_X86_64_TLSDESC_CALL:
case BFD_RELOC_RVA: case BFD_RELOC_RVA:
@ -5776,6 +5825,12 @@ tc_gen_reloc (section, fixp)
else else
code = BFD_RELOC_X86_64_GOTPC32; code = BFD_RELOC_X86_64_GOTPC32;
} }
if ((code == BFD_RELOC_64 || code == BFD_RELOC_64_PCREL)
&& GOT_symbol
&& fixp->fx_addsy == GOT_symbol)
{
code = BFD_RELOC_X86_64_GOTPC64;
}
rel = (arelent *) xmalloc (sizeof (arelent)); rel = (arelent *) xmalloc (sizeof (arelent));
rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *)); rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));

View File

@ -19,6 +19,7 @@ Disassembly of section \.text:
.*[ ]+R_X86_64_PC32[ ]+xtrn\+0xf+c .*[ ]+R_X86_64_PC32[ ]+xtrn\+0xf+c
.*[ ]+R_X86_64_PC32[ ]+xtrn\+0xf+c .*[ ]+R_X86_64_PC32[ ]+xtrn\+0xf+c
.*[ ]+R_X86_64_PC8[ ]+xtrn\+0xf+f .*[ ]+R_X86_64_PC8[ ]+xtrn\+0xf+f
.*[ ]+R_X86_64_GOT64[ ]+xtrn
.*[ ]+R_X86_64_GOT32[ ]+xtrn .*[ ]+R_X86_64_GOT32[ ]+xtrn
.*[ ]+R_X86_64_GOT32[ ]+xtrn .*[ ]+R_X86_64_GOT32[ ]+xtrn
.*[ ]+R_X86_64_GOTOFF64[ ]+xtrn .*[ ]+R_X86_64_GOTOFF64[ ]+xtrn
@ -26,7 +27,7 @@ Disassembly of section \.text:
.*[ ]+R_X86_64_GOTPCREL[ ]+xtrn .*[ ]+R_X86_64_GOTPCREL[ ]+xtrn
.*[ ]+R_X86_64_GOTPCREL[ ]+xtrn\+0xf+c .*[ ]+R_X86_64_GOTPCREL[ ]+xtrn\+0xf+c
.*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0x0*2 .*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0x0*2
.*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0xf+f .*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0xf+c
.*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0x0*2 .*[ ]+R_X86_64_GOTPC32[ ]+_GLOBAL_OFFSET_TABLE_\+0x0*2
.*[ ]+R_X86_64_PLT32[ ]+xtrn .*[ ]+R_X86_64_PLT32[ ]+xtrn
.*[ ]+R_X86_64_PLT32[ ]+xtrn .*[ ]+R_X86_64_PLT32[ ]+xtrn
@ -50,7 +51,9 @@ Disassembly of section \.data:
#... #...
.*[ ]+R_X86_64_64[ ]+xtrn .*[ ]+R_X86_64_64[ ]+xtrn
.*[ ]+R_X86_64_PC64[ ]+xtrn .*[ ]+R_X86_64_PC64[ ]+xtrn
.*[ ]+R_X86_64_GOT64[ ]+xtrn
.*[ ]+R_X86_64_GOTOFF64[ ]+xtrn .*[ ]+R_X86_64_GOTOFF64[ ]+xtrn
.*[ ]+R_X86_64_GOTPCREL64[ ]+xtrn
.*[ ]+R_X86_64_DTPOFF64[ ]+xtrn .*[ ]+R_X86_64_DTPOFF64[ ]+xtrn
.*[ ]+R_X86_64_TPOFF64[ ]+xtrn .*[ ]+R_X86_64_TPOFF64[ ]+xtrn
.*[ ]+R_X86_64_32[ ]+xtrn .*[ ]+R_X86_64_32[ ]+xtrn

View File

@ -1,6 +1,5 @@
.*: Assembler messages: .*: Assembler messages:
.*:29: Error: .* .*:29: Error: .*
.*:33: Error: .*
.*:35: Error: .* .*:35: Error: .*
.*:36: Error: .* .*:36: Error: .*
.*:37: Error: .* .*:37: Error: .*
@ -50,8 +49,6 @@
.*:123: Error: .* .*:123: Error: .*
.*:125: Error: .* .*:125: Error: .*
.*:126: Error: .* .*:126: Error: .*
.*:131: Error: .*
.*:133: Error: .*
.*:136: Error: .* .*:136: Error: .*
.*:137: Error: .* .*:137: Error: .*
.*:138: Error: .* .*:138: Error: .*

View File

@ -30,7 +30,7 @@ bad mov xtrn(%eip), %eax
call xtrn call xtrn
jrcxz xtrn jrcxz xtrn
bad movabs $xtrn@got, %rax movabs $xtrn@got, %rax
add $xtrn@got, %rax add $xtrn@got, %rax
bad mov $xtrn@got, %eax bad mov $xtrn@got, %eax
bad mov $xtrn@got, %ax bad mov $xtrn@got, %ax
@ -128,9 +128,9 @@ bad call xtrn@tpoff
.data .data
.quad xtrn .quad xtrn
.quad xtrn - . .quad xtrn - .
bad .quad xtrn@got .quad xtrn@got
.quad xtrn@gotoff .quad xtrn@gotoff
bad .quad xtrn@gotpcrel .quad xtrn@gotpcrel
ill .quad _GLOBAL_OFFSET_TABLE_ ill .quad _GLOBAL_OFFSET_TABLE_
ill .quad _GLOBAL_OFFSET_TABLE_ - . ill .quad _GLOBAL_OFFSET_TABLE_ - .
bad .quad xtrn@plt bad .quad xtrn@plt

View File

@ -54,7 +54,16 @@ START_RELOC_NUMBERS (elf_x86_64_reloc_type)
RELOC_NUMBER (R_X86_64_GOTOFF64, 25) /* 64 bit offset to GOT */ RELOC_NUMBER (R_X86_64_GOTOFF64, 25) /* 64 bit offset to GOT */
RELOC_NUMBER (R_X86_64_GOTPC32, 26) /* 32 bit signed pc relative RELOC_NUMBER (R_X86_64_GOTPC32, 26) /* 32 bit signed pc relative
offset to GOT */ offset to GOT */
/* 27 .. 33 */ RELOC_NUMBER (R_X86_64_GOT64, 27) /* 64 bit GOT entry offset */
RELOC_NUMBER (R_X86_64_GOTPCREL64, 28) /* 64 bit signed pc relative
offset to GOT entry */
RELOC_NUMBER (R_X86_64_GOTPC64, 29) /* 64 bit signed pc relative
offset to GOT */
RELOC_NUMBER (R_X86_64_GOTPLT64, 30) /* like GOT64, but indicates
that PLT entry is needed */
RELOC_NUMBER (R_X86_64_PLTOFF64, 31) /* 64 bit GOT relative offset
to PLT entry */
/* 32 .. 33 */
RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34) RELOC_NUMBER (R_X86_64_GOTPC32_TLSDESC, 34)
/* 32 bit signed pc relative /* 32 bit signed pc relative
offset to TLS descriptor offset to TLS descriptor