mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 10:03:47 +08:00
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:
parent
c5f44798e0
commit
7b81dfbbf9
@ -2707,6 +2707,11 @@ in the instruction. */
|
||||
BFD_RELOC_X86_64_TPOFF32,
|
||||
BFD_RELOC_X86_64_GOTOFF64,
|
||||
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_TLSDESC_CALL,
|
||||
BFD_RELOC_X86_64_TLSDESC,
|
||||
|
@ -31,8 +31,8 @@
|
||||
#define MINUS_ONE (~ (bfd_vma) 0)
|
||||
|
||||
/* The relocation "howto" table. Order of fields:
|
||||
type, size, bitsize, pc_relative, complain_on_overflow,
|
||||
special_function, name, partial_inplace, src_mask, dst_pack, pcrel_offset. */
|
||||
type, rightshift, size, bitsize, pc_relative, bitpos, complain_on_overflow,
|
||||
special_function, name, partial_inplace, src_mask, dst_mask, pcrel_offset. */
|
||||
static reloc_howto_type x86_64_elf_howto_table[] =
|
||||
{
|
||||
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,
|
||||
bfd_elf_generic_reloc, "R_X86_64_GOTPC32",
|
||||
FALSE, 0xffffffff, 0xffffffff, TRUE),
|
||||
EMPTY_HOWTO (27),
|
||||
EMPTY_HOWTO (28),
|
||||
EMPTY_HOWTO (29),
|
||||
EMPTY_HOWTO (30),
|
||||
EMPTY_HOWTO (31),
|
||||
HOWTO(R_X86_64_GOT64, 0, 4, 64, FALSE, 0, complain_overflow_signed,
|
||||
bfd_elf_generic_reloc, "R_X86_64_GOT64", FALSE, MINUS_ONE, MINUS_ONE,
|
||||
FALSE),
|
||||
HOWTO(R_X86_64_GOTPCREL64, 0, 4, 64, TRUE, 0, complain_overflow_signed,
|
||||
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 (33),
|
||||
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_X86_64_GOTOFF64, R_X86_64_GOTOFF64, },
|
||||
{ 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_TLSDESC_CALL, R_X86_64_TLSDESC_CALL, },
|
||||
{ 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_GOTPCREL:
|
||||
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_TLSDESC_CALL:
|
||||
/* 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 (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;
|
||||
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_GOTPC32:
|
||||
case R_X86_64_GOTPC64:
|
||||
create_got:
|
||||
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;
|
||||
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_16:
|
||||
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_GOT32:
|
||||
case R_X86_64_GOTPCREL:
|
||||
case R_X86_64_GOT64:
|
||||
case R_X86_64_GOTPCREL64:
|
||||
case R_X86_64_GOTPLT64:
|
||||
if (h != NULL)
|
||||
{
|
||||
if (r_type == R_X86_64_GOTPLT64 && h->plt.refcount > 0)
|
||||
h->plt.refcount -= 1;
|
||||
if (h->got.refcount > 0)
|
||||
h->got.refcount -= 1;
|
||||
}
|
||||
@ -1215,6 +1257,7 @@ elf64_x86_64_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
|
||||
/* Fall thru */
|
||||
|
||||
case R_X86_64_PLT32:
|
||||
case R_X86_64_PLTOFF64:
|
||||
if (h != NULL)
|
||||
{
|
||||
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. */
|
||||
switch (r_type)
|
||||
{
|
||||
asection *base_got;
|
||||
case R_X86_64_GOT32:
|
||||
case R_X86_64_GOT64:
|
||||
/* Relocation is to the entry for this symbol in the global
|
||||
offset table. */
|
||||
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)
|
||||
abort ();
|
||||
|
||||
@ -2109,6 +2164,19 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
||||
bfd_boolean dyn;
|
||||
|
||||
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;
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -2155,7 +2225,7 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
||||
else
|
||||
{
|
||||
bfd_put_64 (output_bfd, relocation,
|
||||
htab->sgot->contents + off);
|
||||
base_got->contents + off);
|
||||
|
||||
if (info->shared)
|
||||
{
|
||||
@ -2169,8 +2239,8 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
||||
if (s == NULL)
|
||||
abort ();
|
||||
|
||||
outrel.r_offset = (htab->sgot->output_section->vma
|
||||
+ htab->sgot->output_offset
|
||||
outrel.r_offset = (base_got->output_section->vma
|
||||
+ base_got->output_offset
|
||||
+ off);
|
||||
outrel.r_info = ELF64_R_INFO (0, R_X86_64_RELATIVE);
|
||||
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)
|
||||
abort ();
|
||||
|
||||
relocation = htab->sgot->output_section->vma
|
||||
+ htab->sgot->output_offset + off;
|
||||
if (r_type != R_X86_64_GOTPCREL)
|
||||
relocation = base_got->output_section->vma
|
||||
+ base_got->output_offset + off;
|
||||
if (r_type != R_X86_64_GOTPCREL && r_type != R_X86_64_GOTPCREL64)
|
||||
relocation -= htab->sgotplt->output_section->vma
|
||||
- htab->sgotplt->output_offset;
|
||||
|
||||
@ -2224,12 +2294,31 @@ elf64_x86_64_relocate_section (bfd *output_bfd, struct bfd_link_info *info,
|
||||
break;
|
||||
|
||||
case R_X86_64_GOTPC32:
|
||||
case R_X86_64_GOTPC64:
|
||||
/* Use global offset table as symbol value. */
|
||||
relocation = htab->sgotplt->output_section->vma
|
||||
+ htab->sgotplt->output_offset;
|
||||
unresolved_reloc = FALSE;
|
||||
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:
|
||||
/* Relocation is to the entry for this symbol in the
|
||||
procedure linkage table. */
|
||||
|
@ -7,7 +7,7 @@
|
||||
(This include file is not for users of the library.)
|
||||
|
||||
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.
|
||||
|
||||
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_GOTOFF64",
|
||||
"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_TLSDESC_CALL",
|
||||
"BFD_RELOC_X86_64_TLSDESC",
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
/* BFD COFF object file private structure.
|
||||
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.
|
||||
Written by Cygnus Support.
|
||||
|
||||
|
10
bfd/reloc.c
10
bfd/reloc.c
@ -2351,6 +2351,16 @@ ENUMX
|
||||
BFD_RELOC_X86_64_GOTOFF64
|
||||
ENUMX
|
||||
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
|
||||
BFD_RELOC_X86_64_GOTPC32_TLSDESC
|
||||
ENUMX
|
||||
|
@ -1169,13 +1169,12 @@ ps (s)
|
||||
segment_name (S_GET_SEGMENT (s)));
|
||||
}
|
||||
|
||||
struct type_name
|
||||
static struct type_name
|
||||
{
|
||||
unsigned int mask;
|
||||
char *tname;
|
||||
}
|
||||
|
||||
static const type_names[] =
|
||||
const type_names[] =
|
||||
{
|
||||
{ Reg8, "r8" },
|
||||
{ Reg16, "r16" },
|
||||
@ -1238,6 +1237,18 @@ reloc (unsigned int size,
|
||||
if (size == 8)
|
||||
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:
|
||||
other = BFD_RELOC_X86_64_TPOFF64;
|
||||
break;
|
||||
@ -3569,7 +3580,7 @@ check_prefix:
|
||||
#ifdef DEBUG386
|
||||
if (flag_debug)
|
||||
{
|
||||
pi (line, &i);
|
||||
pi ("" /*line*/, &i);
|
||||
}
|
||||
#endif /* DEBUG386 */
|
||||
}
|
||||
@ -3654,7 +3665,9 @@ output_disp (insn_start_frag, insn_start_off)
|
||||
if (GOT_symbol
|
||||
&& GOT_symbol == i.op[n].disps->X_add_symbol
|
||||
&& (((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_add
|
||||
&& ((symbol_get_value_expression
|
||||
@ -3678,10 +3691,17 @@ output_disp (insn_start_frag, insn_start_off)
|
||||
}
|
||||
|
||||
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
|
||||
/* 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;
|
||||
i.op[n].disps->X_add_number += add;
|
||||
}
|
||||
fix_new_exp (frag_now, p - frag_now->fr_literal, size,
|
||||
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. */
|
||||
|
||||
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 == i.op[n].imms->X_add_symbol
|
||||
&& (i.op[n].imms->X_op == O_symbol
|
||||
@ -3816,8 +3837,10 @@ output_imm (insn_start_frag, insn_start_off)
|
||||
|
||||
if (!object_64bit)
|
||||
reloc_type = BFD_RELOC_386_GOTPC;
|
||||
else
|
||||
else if (size == 4)
|
||||
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;
|
||||
}
|
||||
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,
|
||||
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 {
|
||||
const char *str;
|
||||
const enum bfd_reloc_code_real rel[2];
|
||||
const unsigned int types64;
|
||||
} gotrel[] = {
|
||||
{ "PLTOFF", { 0, BFD_RELOC_X86_64_PLTOFF64 }, Imm64 },
|
||||
{ "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 },
|
||||
{ "GOTPCREL", { 0, BFD_RELOC_X86_64_GOTPCREL }, 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 },
|
||||
{ "GOTNTPOFF",{ BFD_RELOC_386_TLS_GOTIE, 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 },
|
||||
{ "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. */
|
||||
md_number_to_chars ((char *) where_to_put_displacement,
|
||||
(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_GOTOFF64:
|
||||
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_TLSDESC_CALL:
|
||||
case BFD_RELOC_RVA:
|
||||
@ -5776,6 +5825,12 @@ tc_gen_reloc (section, fixp)
|
||||
else
|
||||
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->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
|
||||
|
@ -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_PC8[ ]+xtrn\+0xf+f
|
||||
.*[ ]+R_X86_64_GOT64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOT32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOT32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOTOFF64[ ]+xtrn
|
||||
@ -26,7 +27,7 @@ Disassembly of section \.text:
|
||||
.*[ ]+R_X86_64_GOTPCREL[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOTPCREL[ ]+xtrn\+0xf+c
|
||||
.*[ ]+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_PLT32[ ]+xtrn
|
||||
.*[ ]+R_X86_64_PLT32[ ]+xtrn
|
||||
@ -50,7 +51,9 @@ Disassembly of section \.data:
|
||||
#...
|
||||
.*[ ]+R_X86_64_64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_PC64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOT64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOTOFF64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_GOTPCREL64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_DTPOFF64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_TPOFF64[ ]+xtrn
|
||||
.*[ ]+R_X86_64_32[ ]+xtrn
|
||||
|
@ -1,6 +1,5 @@
|
||||
.*: Assembler messages:
|
||||
.*:29: Error: .*
|
||||
.*:33: Error: .*
|
||||
.*:35: Error: .*
|
||||
.*:36: Error: .*
|
||||
.*:37: Error: .*
|
||||
@ -50,8 +49,6 @@
|
||||
.*:123: Error: .*
|
||||
.*:125: Error: .*
|
||||
.*:126: Error: .*
|
||||
.*:131: Error: .*
|
||||
.*:133: Error: .*
|
||||
.*:136: Error: .*
|
||||
.*:137: Error: .*
|
||||
.*:138: Error: .*
|
||||
|
@ -30,7 +30,7 @@ bad mov xtrn(%eip), %eax
|
||||
call xtrn
|
||||
jrcxz xtrn
|
||||
|
||||
bad movabs $xtrn@got, %rax
|
||||
movabs $xtrn@got, %rax
|
||||
add $xtrn@got, %rax
|
||||
bad mov $xtrn@got, %eax
|
||||
bad mov $xtrn@got, %ax
|
||||
@ -128,9 +128,9 @@ bad call xtrn@tpoff
|
||||
.data
|
||||
.quad xtrn
|
||||
.quad xtrn - .
|
||||
bad .quad xtrn@got
|
||||
.quad xtrn@got
|
||||
.quad xtrn@gotoff
|
||||
bad .quad xtrn@gotpcrel
|
||||
.quad xtrn@gotpcrel
|
||||
ill .quad _GLOBAL_OFFSET_TABLE_
|
||||
ill .quad _GLOBAL_OFFSET_TABLE_ - .
|
||||
bad .quad xtrn@plt
|
||||
|
@ -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_GOTPC32, 26) /* 32 bit signed pc relative
|
||||
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)
|
||||
/* 32 bit signed pc relative
|
||||
offset to TLS descriptor
|
||||
|
Loading…
Reference in New Issue
Block a user