/* IA-64 support for 64-bit ELF
- Copyright (C) 1998-2017 Free Software Foundation, Inc.
+ Copyright (C) 1998-2019 Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of BFD, the Binary File Descriptor library.
#include "elf/ia64.h"
#include "objalloc.h"
#include "hashtab.h"
-#include "bfd_stdint.h"
#include "elfxx-ia64.h"
#define ARCH_SIZE NN
/* Given a ELF reloc, return the matching HOWTO structure. */
-static void
+static bfd_boolean
elfNN_ia64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
arelent *bfd_reloc,
Elf_Internal_Rela *elf_reloc)
{
- bfd_reloc->howto
- = ia64_elf_lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
+ unsigned int r_type = ELF32_R_TYPE (elf_reloc->r_info);
+
+ bfd_reloc->howto = ia64_elf_lookup_howto (r_type);
+ if (bfd_reloc->howto == NULL)
+ {
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ abfd, r_type);
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
+
+ return TRUE;
}
\f
#define PLT_HEADER_SIZE (3 * 16)
static const bfd_byte plt_header[PLT_HEADER_SIZE] =
{
- 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21, /* [MMI] mov r2=r14;; */
- 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00, /* addl r14=0,r2 */
- 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
- 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14, /* [MMI] ld8 r16=[r14],8;; */
- 0x10, 0x41, 0x38, 0x30, 0x28, 0x00, /* ld8 r17=[r14],8 */
- 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
- 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10, /* [MIB] ld8 r1=[r14] */
- 0x60, 0x88, 0x04, 0x80, 0x03, 0x00, /* mov b6=r17 */
- 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
+ 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21, /* [MMI] mov r2=r14;; */
+ 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00, /* addl r14=0,r2 */
+ 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
+ 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14, /* [MMI] ld8 r16=[r14],8;; */
+ 0x10, 0x41, 0x38, 0x30, 0x28, 0x00, /* ld8 r17=[r14],8 */
+ 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */
+ 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10, /* [MIB] ld8 r1=[r14] */
+ 0x60, 0x88, 0x04, 0x80, 0x03, 0x00, /* mov b6=r17 */
+ 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
};
static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] =
{
- 0x11, 0x78, 0x00, 0x00, 0x00, 0x24, /* [MIB] mov r15=0 */
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */
- 0x00, 0x00, 0x00, 0x40 /* br.few 0 <PLT0>;; */
+ 0x11, 0x78, 0x00, 0x00, 0x00, 0x24, /* [MIB] mov r15=0 */
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */
+ 0x00, 0x00, 0x00, 0x40 /* br.few 0 <PLT0>;; */
};
static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
{
- 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */
- 0x00, 0x41, 0x3c, 0x70, 0x29, 0xc0, /* ld8.acq r16=[r15],8*/
- 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */
- 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */
- 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
- 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
+ 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */
+ 0x00, 0x41, 0x3c, 0x70, 0x29, 0xc0, /* ld8.acq r16=[r15],8*/
+ 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */
+ 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */
+ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
+ 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */
};
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
static const bfd_byte oor_brl[16] =
{
- 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */
+ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */
0x00, 0x00, 0x00, 0xc0
};
static const bfd_byte oor_ip[48] =
{
- 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, /* movl r15=0 */
+ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, /* movl r15=0 */
0x01, 0x00, 0x00, 0x60,
- 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0 */
- 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, /* mov r16=ip;; */
- 0xf2, 0x80, 0x00, 0x80, /* add r16=r15,r16;; */
- 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */
- 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
- 0x60, 0x00, 0x80, 0x00 /* br b6;; */
+ 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0 */
+ 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, /* mov r16=ip;; */
+ 0xf2, 0x80, 0x00, 0x80, /* add r16=r15,r16;; */
+ 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */
+ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */
+ 0x60, 0x00, 0x80, 0x00 /* br b6;; */
};
static size_t oor_branch_size = sizeof (oor_brl);
1, change it to slot 2. */
if ((irel->r_offset & 3) == 1)
irel->r_offset += 1;
+
+ changed_contents = TRUE;
+ changed_relocs = TRUE;
}
continue;
/* Make the relocation offset point to slot 1. */
irel->r_offset = (irel->r_offset & ~((bfd_vma) 0x3)) + 1;
+
+ changed_contents = TRUE;
+ changed_relocs = TRUE;
continue;
}
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: Can't relax br at 0x%lx in section `%A'."
- " Please use brl or indirect branch."),
- sec->owner, (unsigned long) roff, sec);
+ (_("%pB: can't relax br at %#" PRIx64 " in section `%pA';"
+ " please use brl or indirect branch"),
+ sec->owner, (uint64_t) roff, sec);
bfd_set_error (bfd_error_bad_value);
goto error_return;
}
if (create)
{
/* When we create the array, we don't check for duplicates,
- except in the previously sorted section if one exists, and
+ except in the previously sorted section if one exists, and
against the last inserted entry. This allows insertions to
be fast. */
if (info)
else
h = NULL;
+ if (h && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ continue;
+
/* We can only get preliminary data on whether a symbol is
locally or externally defined, as not all of the input files
have yet been processed. Do something with what we know, as
break;
case R_IA64_PCREL21B:
- case R_IA64_PCREL60B:
+ case R_IA64_PCREL60B:
/* Depending on where this symbol is defined, we may or may not
need a full plt entry. Only skip if we know we'll not need
the entry -- static or symbolic, and the symbol definition
/* PR15323, ref flags aren't set for references in the same
object. */
- h->root.non_ir_ref = 1;
h->ref_regular = 1;
}
else
h = NULL;
+ if (h && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
+ continue;
+
/* We can only get preliminary data on whether a symbol is
locally or externally defined, as not all of the input files
have yet been processed. Do something with what we know, as
break;
case R_IA64_PCREL21B:
- case R_IA64_PCREL60B:
+ case R_IA64_PCREL60B:
/* Depending on where this symbol is defined, we may or may not
need a full plt entry. Only skip if we know we'll not need
the entry -- static or symbolic, and the symbol definition
dyn_i->want_ltoff_fptr = 1;
if (need_entry & (NEED_MIN_PLT | NEED_FULL_PLT))
{
- if (!ia64_info->root.dynobj)
+ if (!ia64_info->root.dynobj)
ia64_info->root.dynobj = abfd;
h->needs_plt = 1;
dyn_i->want_plt = 1;
if (!bfd_link_executable (x->info)
&& (!h
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (x->info, h))
|| (h->root.type != bfd_link_hash_undefweak
&& h->root.type != bfd_link_hash_undefined)))
{
shared = bfd_link_pic (x->info);
resolved_zero = (dyn_i->h
- && ELF_ST_VISIBILITY (dyn_i->h->other)
- && dyn_i->h->root.type == bfd_link_hash_undefweak);
+ && UNDEFWEAK_NO_DYNAMIC_RELOC (x->info,
+ dyn_i->h));
/* Take care of the GOT and PLT relocations. */
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->u.weakdef != NULL)
+ if (h->is_weakalias)
{
- BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
- || h->u.weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->u.weakdef->root.u.def.section;
- h->root.u.def.value = h->u.weakdef->root.u.def.value;
+ struct elf_link_hash_entry *def = weakdef (h);
+ BFD_ASSERT (def->root.type == bfd_link_hash_defined);
+ h->root.u.def.section = def->root.u.def.section;
+ h->root.u.def.value = def->root.u.def.value;
return TRUE;
}
/* Install a dynamic relocation if needed. */
if (((bfd_link_pic (info)
&& (!dyn_i->h
- || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, dyn_i->h))
|| dyn_i->h->root.type != bfd_link_hash_undefweak)
&& dyn_r_type != R_IA64_DTPREL32LSB
&& dyn_r_type != R_IA64_DTPREL64LSB)
- || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
+ || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info, dyn_r_type)
|| (dynindx != -1
&& (dyn_r_type == R_IA64_FPTR32LSB
|| dyn_r_type == R_IA64_FPTR64LSB)))
if (!is_plt
&& bfd_link_pic (info)
&& (!dyn_i->h
- || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ || (ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, dyn_i->h))
|| dyn_i->h->root.type != bfd_link_hash_undefweak))
{
unsigned int dyn_r_type;
overflow:
_bfd_error_handler
/* xgettext:c-format */
- (_("%s: short data segment overflowed (0x%lx >= 0x400000)"),
- bfd_get_filename (abfd),
- (unsigned long) (max_short_vma - min_short_vma));
+ (_("%pB: short data segment overflowed (%#" PRIx64 " >= 0x400000)"),
+ abfd, (uint64_t) (max_short_vma - min_short_vma));
return FALSE;
}
else if ((gp_val > min_short_vma
&& max_short_vma - gp_val >= 0x200000))
{
_bfd_error_handler
- (_("%s: __gp does not cover short data segment"),
- bfd_get_filename (abfd));
+ (_("%pB: __gp does not cover short data segment"), abfd);
return FALSE;
}
}
gp_val = _bfd_get_gp_value (abfd);
gp = elf_link_hash_lookup (elf_hash_table (info), "__gp", FALSE,
- FALSE, FALSE);
+ FALSE, FALSE);
if (gp)
{
gp->root.type = bfd_link_hash_defined;
r_type = ELFNN_R_TYPE (rel->r_info);
if (r_type > R_IA64_MAX_RELOC_CODE)
{
- _bfd_error_handler
- /* xgettext:c-format */
- (_("%B: unknown relocation type %d"),
- input_bfd, (int) r_type);
+ /* xgettext:c-format */
+ _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
+ input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret_val = FALSE;
continue;
}
howto = ia64_elf_lookup_howto (r_type);
+ if (howto == NULL)
+ {
+ ret_val = FALSE;
+ continue;
+ }
+
r_symndx = ELFNN_R_SYM (rel->r_info);
h = NULL;
sym = NULL;
case R_IA64_DIR64LSB:
/* Install a dynamic relocation for this reloc. */
if ((dynamic_symbol_p || bfd_link_pic (info))
+ && !(h && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
&& r_symndx != STN_UNDEF
&& (input_section->flags & SEC_ALLOC) != 0)
{
shared libraries nor dynamic executables. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: non-pic code with imm relocation against dynamic symbol `%s'"),
+ (_("%pB: non-pic code with imm relocation against dynamic symbol `%s'"),
input_bfd,
h ? h->root.root.string
: bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
{
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: @gprel relocation against dynamic symbol %s"),
+ (_("%pB: @gprel relocation against dynamic symbol %s"),
input_bfd,
h ? h->root.root.string
: bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
case R_IA64_LTOFF22:
case R_IA64_LTOFF22X:
case R_IA64_LTOFF64I:
- dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
+ dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
rel->r_addend, value, R_IA64_DIRNNLSB);
value -= gp_val;
case R_IA64_PLTOFF64I:
case R_IA64_PLTOFF64MSB:
case R_IA64_PLTOFF64LSB:
- dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
+ dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
value = set_pltoff_entry (output_bfd, info, dyn_i, value, FALSE);
value -= gp_val;
r = ia64_elf_install_value (hit_addr, value, r_type);
case R_IA64_FPTR32LSB:
case R_IA64_FPTR64MSB:
case R_IA64_FPTR64LSB:
- dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
+ dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
if (dyn_i->want_fptr)
{
if (!undef_weak_ref)
/* ??? People shouldn't be doing non-pic code in
shared libraries. Hork. */
_bfd_error_handler
- (_("%B: linking non-pic code in a position independent executable"),
+ (_("%pB: linking non-pic code in a position independent executable"),
input_bfd);
ret_val = FALSE;
continue;
if (dyn_i->want_fptr)
{
BFD_ASSERT (h == NULL || h->dynindx == -1);
- if (!undef_weak_ref)
- value = set_fptr_entry (output_bfd, info, dyn_i, value);
+ if (!undef_weak_ref)
+ value = set_fptr_entry (output_bfd, info, dyn_i, value);
dynindx = -1;
}
else
{
- /* Otherwise, we expect the dynamic linker to create
+ /* Otherwise, we expect the dynamic linker to create
the entry. */
- if (h)
+ if (h)
{
if (h->dynindx != -1)
dynindx = h->dynindx;
if (r_type == R_IA64_PCREL21BI)
/* xgettext:c-format */
- msg = _("%B: @internal branch to dynamic symbol %s");
+ msg = _("%pB: @internal branch to dynamic symbol %s");
else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
/* xgettext:c-format */
- msg = _("%B: speculation fixup to dynamic symbol %s");
+ msg = _("%pB: speculation fixup to dynamic symbol %s");
else
/* xgettext:c-format */
- msg = _("%B: @pcrel relocation against dynamic symbol %s");
+ msg = _("%pB: @pcrel relocation against dynamic symbol %s");
_bfd_error_handler (msg, input_bfd,
h ? h->root.root.string
: bfd_elf_sym_name (input_bfd,
case R_IA64_LTOFF_DTPREL22:
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: missing TLS section for relocation %s against `%s'"
- " at 0x%lx in section `%A'."),
+ (_("%pB: missing TLS section for relocation %s against `%s'"
+ " at %#" PRIx64 " in section `%pA'."),
input_bfd, howto->name, name,
- rel->r_offset, input_section);
+ (uint64_t) rel->r_offset, input_section);
break;
case R_IA64_PCREL21B:
that the section is too big to relax. */
_bfd_error_handler
/* xgettext:c-format */
- (_("%B: Can't relax br (%s) to `%s' at 0x%lx"
- " in section `%A' with size 0x%lx (> 0x1000000)."),
- input_bfd, howto->name, name, rel->r_offset,
- input_section, input_section->size);
+ (_("%pB: Can't relax br (%s) to `%s' at %#" PRIx64
+ " in section `%pA' with size %#" PRIx64
+ " (> 0x1000000)."),
+ input_bfd, howto->name, name, (uint64_t) rel->r_offset,
+ input_section, (uint64_t) input_section->size);
break;
}
/* Fall through. */
if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
{
_bfd_error_handler
- (_("%B: linking trap-on-NULL-dereference with non-trapping files"),
+ (_("%pB: linking trap-on-NULL-dereference with non-trapping files"),
ibfd);
bfd_set_error (bfd_error_bad_value);
if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
{
_bfd_error_handler
- (_("%B: linking big-endian files with little-endian files"),
+ (_("%pB: linking big-endian files with little-endian files"),
ibfd);
bfd_set_error (bfd_error_bad_value);
if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
{
_bfd_error_handler
- (_("%B: linking 64-bit files with 32-bit files"),
+ (_("%pB: linking 64-bit files with 32-bit files"),
ibfd);
bfd_set_error (bfd_error_bad_value);
if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
{
_bfd_error_handler
- (_("%B: linking constant-gp files with non-constant-gp files"),
+ (_("%pB: linking constant-gp files with non-constant-gp files"),
ibfd);
bfd_set_error (bfd_error_bad_value);
!= (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
{
_bfd_error_handler
- (_("%B: linking auto-pic files with non-auto-pic files"),
+ (_("%pB: linking auto-pic files with non-auto-pic files"),
ibfd);
bfd_set_error (bfd_error_bad_value);
static const struct bfd_elf_special_section elfNN_ia64_special_sections[] =
{
- { STRING_COMMA_LEN (".sbss"), -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
+ { STRING_COMMA_LEN (".sbss"), -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
{ STRING_COMMA_LEN (".sdata"), -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
- { NULL, 0, 0, 0, 0 }
+ { NULL, 0, 0, 0, 0 }
};
static bfd_boolean
#define elf_backend_size_dynamic_sections \
elfNN_ia64_size_dynamic_sections
#define elf_backend_omit_section_dynsym \
- ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
+ _bfd_elf_omit_section_dynsym_all
#define elf_backend_relocate_section \
elfNN_ia64_relocate_section
#define elf_backend_finish_dynamic_symbol \
elfNN_ia64_print_private_bfd_data
#define elf_backend_plt_readonly 1
+#define elf_backend_can_gc_sections 1
#define elf_backend_want_plt_sym 0
#define elf_backend_plt_alignment 5
#define elf_backend_got_header_size 0
#undef TARGET_LITTLE_SYM
#undef TARGET_LITTLE_NAME
#undef TARGET_BIG_SYM
-#define TARGET_BIG_SYM ia64_elfNN_hpux_be_vec
-#undef TARGET_BIG_NAME
-#define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
+#define TARGET_BIG_SYM ia64_elfNN_hpux_be_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
/* These are HP-UX specific functions. */