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_SIZE32, 0, 2, 32, FALSE, 0, complain_overflow_unsigned,
+ bfd_elf_generic_reloc, "R_X86_64_SIZE32", FALSE, 0xffffffff, 0xffffffff,
+ FALSE),
+ HOWTO(R_X86_64_SIZE64, 0, 4, 64, FALSE, 0, complain_overflow_unsigned,
+ bfd_elf_generic_reloc, "R_X86_64_SIZE64", FALSE, MINUS_ONE, MINUS_ONE,
+ FALSE),
HOWTO(R_X86_64_GOTPC32_TLSDESC, 0, 2, 32, TRUE, 0,
complain_overflow_bitfield, bfd_elf_generic_reloc,
"R_X86_64_GOTPC32_TLSDESC",
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_GNU_VT* to form an index into this table. */
-#define R_X86_64_standard (R_X86_64_IRELATIVE + 1)
+#define R_X86_64_standard (R_X86_64_RELATIVE64 + 1)
#define R_X86_64_vt_offset (R_X86_64_GNU_VTINHERIT - R_X86_64_standard)
/* GNU extension to record C++ vtable hierarchy. */
{ 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_SIZE32, R_X86_64_SIZE32, },
+ { BFD_RELOC_SIZE64, R_X86_64_SIZE64, },
{ 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, },
}
else
{
- prpsinfo_t data;
+ prpsinfo64_t data;
memset (&data, 0, sizeof (data));
strncpy (data.pr_fname, fname, sizeof (data.pr_fname));
strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs));
}
else
{
- prstatus_t prstat;
+ prstatus64_t prstat;
memset (&prstat, 0, sizeof (prstat));
prstat.pr_pid = pid;
prstat.pr_cursig = cursig;
break;
}
- /* Since STT_GNU_IFUNC symbol must go through PLT, we handle
- it here if it is defined in a non-shared object. */
- if (h->type == STT_GNU_IFUNC
- && h->def_regular)
- {
- /* It is referenced by a non-shared object. */
- h->ref_regular = 1;
- h->needs_plt = 1;
-
- /* STT_GNU_IFUNC symbol must go through PLT. */
- h->plt.refcount += 1;
-
- /* STT_GNU_IFUNC needs dynamic sections. */
- if (htab->elf.dynobj == NULL)
- htab->elf.dynobj = abfd;
-
- switch (r_type)
- {
- default:
- if (h->root.root.string)
- name = h->root.root.string;
- else
- name = bfd_elf_sym_name (abfd, symtab_hdr, isym,
- NULL);
- (*_bfd_error_handler)
- (_("%B: relocation %s against STT_GNU_IFUNC "
- "symbol `%s' isn't handled by %s"), abfd,
- x86_64_elf_howto_table[r_type].name,
- name, __FUNCTION__);
- bfd_set_error (bfd_error_bad_value);
- return FALSE;
-
- case R_X86_64_32:
- if (ABI_64_P (abfd))
- goto not_pointer;
- case R_X86_64_64:
- h->non_got_ref = 1;
- h->pointer_equality_needed = 1;
- if (info->shared)
- {
- /* We must copy these reloc types into the output
- file. Create a reloc section in dynobj and
- make room for this reloc. */
- sreloc = _bfd_elf_create_ifunc_dyn_reloc
- (abfd, info, sec, sreloc,
- &((struct elf_x86_64_link_hash_entry *) h)->dyn_relocs);
- if (sreloc == NULL)
- return FALSE;
- }
- break;
-
- case R_X86_64_32S:
- case R_X86_64_PC32:
- case R_X86_64_PC64:
-not_pointer:
- h->non_got_ref = 1;
- if (r_type != R_X86_64_PC32
- && r_type != R_X86_64_PC64)
- h->pointer_equality_needed = 1;
- break;
-
- case R_X86_64_PLT32:
- break;
-
- case R_X86_64_GOTPCREL:
- case R_X86_64_GOTPCREL64:
- h->got.refcount += 1;
- if (htab->elf.sgot == NULL
- && !_bfd_elf_create_got_section (htab->elf.dynobj,
- info))
- return FALSE;
- break;
- }
-
- continue;
- }
+ /* It is referenced by a non-shared object. */
+ h->ref_regular = 1;
}
if (! elf_x86_64_tls_transition (info, abfd, sec, NULL,
(*_bfd_error_handler)
(_("%B: '%s' accessed both as normal and thread local symbol"),
abfd, name);
+ bfd_set_error (bfd_error_bad_value);
return FALSE;
}
}
case R_X86_64_PC32:
case R_X86_64_PC64:
case R_X86_64_64:
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
pointer:
if (h != NULL && info->executable)
{
case R_X86_64_PC16:
case R_X86_64_PC32:
case R_X86_64_PC64:
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
if (info->shared
&& (h == NULL || h->type != STT_GNU_IFUNC))
break;
{
struct elf_x86_64_link_hash_table *htab;
asection *s;
+ struct elf_x86_64_link_hash_entry *eh;
+ struct elf_dyn_relocs *p;
/* STT_GNU_IFUNC symbol must go through PLT. */
if (h->type == STT_GNU_IFUNC)
{
+ /* All local STT_GNU_IFUNC references must be treate as local
+ calls via local PLT. */
+ if (h->ref_regular
+ && SYMBOL_CALLS_LOCAL (info, h))
+ {
+ bfd_size_type pc_count = 0, count = 0;
+ struct elf_dyn_relocs **pp;
+
+ eh = (struct elf_x86_64_link_hash_entry *) h;
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
+ {
+ pc_count += p->pc_count;
+ p->count -= p->pc_count;
+ p->pc_count = 0;
+ count += p->count;
+ if (p->count == 0)
+ *pp = p->next;
+ else
+ pp = &p->next;
+ }
+
+ if (pc_count || count)
+ {
+ h->needs_plt = 1;
+ h->non_got_ref = 1;
+ if (h->plt.refcount <= 0)
+ h->plt.refcount = 1;
+ else
+ h->plt.refcount += 1;
+ }
+ }
+
if (h->plt.refcount <= 0)
{
h->plt.offset = (bfd_vma) -1;
if (ELIMINATE_COPY_RELOCS)
{
- struct elf_x86_64_link_hash_entry * eh;
- struct elf_dyn_relocs *p;
-
eh = (struct elf_x86_64_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
if (!is_elf_hash_table (link_info->hash))
return FALSE;
- /* Nothing to do if there are no codes or no relocations. */
+ /* Nothing to do if there are no codes, no relocations or no output. */
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
- || sec->reloc_count == 0)
+ || sec->reloc_count == 0
+ || discarded_section (sec))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
address. */
if (h->def_regular
&& h->type != STT_GNU_IFUNC
- && strcmp (h->root.root.string, "_DYNAMIC") != 0
+ && h != htab->elf.hdynamic
&& SYMBOL_REFERENCES_LOCAL (link_info, h)
&& bfd_get_8 (input_bfd,
contents + irel->r_offset - 2) == 0x8b)
if (htab->elf.sgotplt)
{
- struct elf_link_hash_entry *got;
- got = elf_link_hash_lookup (elf_hash_table (info),
- "_GLOBAL_OFFSET_TABLE_",
- FALSE, FALSE, FALSE);
-
/* Don't allocate .got.plt section if there are no GOT nor PLT
entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */
- if ((got == NULL
- || !got->ref_regular_nonweak)
+ if ((htab->elf.hgot == NULL
+ || !htab->elf.hgot->ref_regular_nonweak)
&& (htab->elf.sgotplt->size
== get_elf_backend_data (output_bfd)->got_header_size)
&& (htab->elf.splt == NULL
bfd_reloc_status_type r;
int tls_type;
asection *base_got;
+ bfd_vma st_size;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type == (int) R_X86_64_GNU_VTINHERIT
|| r_type == (int) R_X86_64_GNU_VTENTRY)
continue;
- if (r_type >= R_X86_64_max)
+ if (r_type >= (int) R_X86_64_standard)
{
+ (*_bfd_error_handler)
+ (_("%B: unrecognized relocation (0x%x) in section `%A'"),
+ input_bfd, input_section, r_type);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
relocation = _bfd_elf_rela_local_sym (output_bfd, sym,
&sec, rel);
+ st_size = sym->st_size;
/* Relocate against local STT_GNU_IFUNC symbol. */
if (!info->relocatable
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
unresolved_reloc, warned);
+ st_size = h->size;
}
if (sec != NULL && discarded_section (sec))
if (info->relocatable)
continue;
- if (rel->r_addend == 0
- && r_type == R_X86_64_64
- && !ABI_64_P (output_bfd))
+ if (rel->r_addend == 0 && !ABI_64_P (output_bfd))
{
- /* For x32, treat R_X86_64_64 like R_X86_64_32 and zero-extend
- it to 64bit if addend is zero. */
- r_type = R_X86_64_32;
- memset (contents + rel->r_offset + 4, 0, 4);
+ if (r_type == R_X86_64_64)
+ {
+ /* For x32, treat R_X86_64_64 like R_X86_64_32 and
+ zero-extend it to 64bit if addend is zero. */
+ r_type = R_X86_64_32;
+ memset (contents + rel->r_offset + 4, 0, 4);
+ }
+ else if (r_type == R_X86_64_SIZE64)
+ {
+ /* For x32, treat R_X86_64_SIZE64 like R_X86_64_SIZE32 and
+ zero-extend it to 64bit if addend is zero. */
+ r_type = R_X86_64_SIZE32;
+ memset (contents + rel->r_offset + 4, 0, 4);
+ }
}
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
unresolved_reloc = FALSE;
break;
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
+ if (h
+ && h->type == STT_TLS
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)
+ && h->root.u.def.section->output_section != NULL
+ && htab->elf.tls_sec == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%B: `%s' accessed both as normal and thread local symbol"),
+ input_bfd, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ /* Set to symbol size. */
+ relocation = st_size;
+ goto direct;
+
case R_X86_64_PC8:
case R_X86_64_PC16:
case R_X86_64_PC32:
/* FIXME: The ABI says the linker should make sure the value is
the same when it's zeroextended to 64 bit. */
+direct:
if ((input_section->flags & SEC_ALLOC) == 0)
break;
&& (h == NULL
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|| h->root.type != bfd_link_hash_undefweak)
- && (! IS_X86_64_PCREL_TYPE (r_type)
+ && ((! IS_X86_64_PCREL_TYPE (r_type)
+ && r_type != R_X86_64_SIZE32
+ && r_type != R_X86_64_SIZE64)
|| ! SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
&& !info->shared
|| plt == NULL
|| gotplt == NULL
|| relplt == NULL)
- return FALSE;
+ abort ();
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol