/* IA-64 support for 64-bit ELF
- Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "opcode/ia64.h"
#define elfNN_ia64_hash_table(p) \
((struct elfNN_ia64_link_hash_table *) ((p)->hash))
-static bfd_reloc_status_type elfNN_ia64_reloc
- PARAMS ((bfd *abfd, arelent *reloc, asymbol *sym, PTR data,
- asection *input_section, bfd *output_bfd, char **error_message));
-static reloc_howto_type * lookup_howto
- PARAMS ((unsigned int rtype));
-static reloc_howto_type *elfNN_ia64_reloc_type_lookup
- PARAMS ((bfd *abfd, bfd_reloc_code_real_type bfd_code));
-static void elfNN_ia64_info_to_howto
- PARAMS ((bfd *abfd, arelent *bfd_reloc, Elf_Internal_Rela *elf_reloc));
-static bfd_boolean elfNN_ia64_relax_section
- PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
- bfd_boolean *again));
-static void elfNN_ia64_relax_ldxmov
- PARAMS((bfd_byte *contents, bfd_vma off));
-static bfd_boolean is_unwind_section_name
- PARAMS ((bfd *abfd, const char *));
-static bfd_boolean elfNN_ia64_section_flags
- PARAMS ((flagword *, const Elf_Internal_Shdr *));
-static bfd_boolean elfNN_ia64_fake_sections
- PARAMS ((bfd *abfd, Elf_Internal_Shdr *hdr, asection *sec));
-static void elfNN_ia64_final_write_processing
- PARAMS ((bfd *abfd, bfd_boolean linker));
-static bfd_boolean elfNN_ia64_add_symbol_hook
- PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym,
- const char **namep, flagword *flagsp, asection **secp,
- bfd_vma *valp));
-static bfd_boolean elfNN_ia64_is_local_label_name
- PARAMS ((bfd *abfd, const char *name));
+static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
+ (struct elfNN_ia64_link_hash_table *ia64_info,
+ struct elf_link_hash_entry *h,
+ bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create);
static bfd_boolean elfNN_ia64_dynamic_symbol_p
- PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
-static struct bfd_hash_entry *elfNN_ia64_new_elf_hash_entry
- PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
- const char *string));
-static void elfNN_ia64_hash_copy_indirect
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *,
- struct elf_link_hash_entry *));
-static void elfNN_ia64_hash_hide_symbol
- PARAMS ((struct bfd_link_info *, struct elf_link_hash_entry *, bfd_boolean));
-static hashval_t elfNN_ia64_local_htab_hash PARAMS ((const void *));
-static int elfNN_ia64_local_htab_eq PARAMS ((const void *ptr1,
- const void *ptr2));
-static struct bfd_link_hash_table *elfNN_ia64_hash_table_create
- PARAMS ((bfd *abfd));
-static void elfNN_ia64_hash_table_free
- PARAMS ((struct bfd_link_hash_table *hash));
-static bfd_boolean elfNN_ia64_global_dyn_sym_thunk
- PARAMS ((struct bfd_hash_entry *, PTR));
-static int elfNN_ia64_local_dyn_sym_thunk
- PARAMS ((void **, PTR));
+ (struct elf_link_hash_entry *h, struct bfd_link_info *info, int);
+static bfd_reloc_status_type elfNN_ia64_install_value
+ (bfd_byte *hit_addr, bfd_vma val, unsigned int r_type);
+static bfd_boolean elfNN_ia64_choose_gp
+ (bfd *abfd, struct bfd_link_info *info);
+static void elfNN_ia64_relax_ldxmov
+ (bfd_byte *contents, bfd_vma off);
static void elfNN_ia64_dyn_sym_traverse
- PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
- bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
- PTR info));
-static bfd_boolean elfNN_ia64_create_dynamic_sections
- PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static struct elfNN_ia64_local_hash_entry * get_local_sym_hash
- PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
- bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
-static struct elfNN_ia64_dyn_sym_info * get_dyn_sym_info
- PARAMS ((struct elfNN_ia64_link_hash_table *ia64_info,
- struct elf_link_hash_entry *h,
- bfd *abfd, const Elf_Internal_Rela *rel, bfd_boolean create));
-static asection *get_got
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_fptr
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_pltoff
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_link_hash_table *ia64_info));
-static asection *get_reloc_section
- PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
- asection *sec, bfd_boolean create));
-static bfd_boolean elfNN_ia64_check_relocs
- PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
- const Elf_Internal_Rela *relocs));
-static bfd_boolean elfNN_ia64_adjust_dynamic_symbol
- PARAMS ((struct bfd_link_info *info, struct elf_link_hash_entry *h));
-static long global_sym_index
- PARAMS ((struct elf_link_hash_entry *h));
-static bfd_boolean allocate_fptr
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+ (struct elfNN_ia64_link_hash_table *ia64_info,
+ bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
+ PTR info);
static bfd_boolean allocate_global_data_got
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+ (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
static bfd_boolean allocate_global_fptr_got
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
+ (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
static bfd_boolean allocate_local_got
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_pltoff_entries
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_plt_entries
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_plt2_entries
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean allocate_dynrel_entries
- PARAMS ((struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data));
-static bfd_boolean elfNN_ia64_size_dynamic_sections
- PARAMS ((bfd *output_bfd, struct bfd_link_info *info));
-static bfd_reloc_status_type elfNN_ia64_install_value
- PARAMS ((bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
-static void elfNN_ia64_install_dyn_reloc
- PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
- asection *srel, bfd_vma offset, unsigned int type,
- long dynindx, bfd_vma addend));
-static bfd_vma set_got_entry
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_dyn_sym_info *dyn_i, long dynindx,
- bfd_vma addend, bfd_vma value, unsigned int dyn_r_type));
-static bfd_vma set_fptr_entry
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_dyn_sym_info *dyn_i,
- bfd_vma value));
-static bfd_vma set_pltoff_entry
- PARAMS ((bfd *abfd, struct bfd_link_info *info,
- struct elfNN_ia64_dyn_sym_info *dyn_i,
- bfd_vma value, bfd_boolean));
-static bfd_vma elfNN_ia64_tprel_base
- PARAMS ((struct bfd_link_info *info));
-static bfd_vma elfNN_ia64_dtprel_base
- PARAMS ((struct bfd_link_info *info));
-static int elfNN_ia64_unwind_entry_compare
- PARAMS ((const PTR, const PTR));
-static bfd_boolean elfNN_ia64_choose_gp
- PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_final_link
- PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_relocate_section
- PARAMS ((bfd *output_bfd, struct bfd_link_info *info, bfd *input_bfd,
- asection *input_section, bfd_byte *contents,
- Elf_Internal_Rela *relocs, Elf_Internal_Sym *local_syms,
- asection **local_sections));
-static bfd_boolean elfNN_ia64_finish_dynamic_symbol
- PARAMS ((bfd *output_bfd, struct bfd_link_info *info,
- struct elf_link_hash_entry *h, Elf_Internal_Sym *sym));
-static bfd_boolean elfNN_ia64_finish_dynamic_sections
- PARAMS ((bfd *abfd, struct bfd_link_info *info));
-static bfd_boolean elfNN_ia64_set_private_flags
- PARAMS ((bfd *abfd, flagword flags));
-static bfd_boolean elfNN_ia64_merge_private_bfd_data
- PARAMS ((bfd *ibfd, bfd *obfd));
-static bfd_boolean elfNN_ia64_print_private_bfd_data
- PARAMS ((bfd *abfd, PTR ptr));
-static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
- PARAMS ((const Elf_Internal_Rela *));
+ (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
static bfd_boolean elfNN_ia64_hpux_vec
- PARAMS ((const bfd_target *vec));
-static void elfNN_hpux_post_process_headers
- PARAMS ((bfd *abfd, struct bfd_link_info *info));
-bfd_boolean elfNN_hpux_backend_section_from_bfd_section
- PARAMS ((bfd *abfd, asection *sec, int *retval));
+ (const bfd_target *vec);
+static bfd_boolean allocate_dynrel_entries
+ (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data);
+static asection *get_pltoff
+ (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_link_hash_table *ia64_info);
\f
/* ia64-specific relocation. */
/* Perform a relocation. Not much to do here as all the hard work is
done in elfNN_ia64_final_link_relocate. */
static bfd_reloc_status_type
-elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
- output_bfd, error_message)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *reloc;
- asymbol *sym ATTRIBUTE_UNUSED;
- PTR data ATTRIBUTE_UNUSED;
- asection *input_section;
- bfd *output_bfd;
- char **error_message;
+elfNN_ia64_reloc (bfd *abfd ATTRIBUTE_UNUSED, arelent *reloc,
+ asymbol *sym ATTRIBUTE_UNUSED,
+ PTR data ATTRIBUTE_UNUSED, asection *input_section,
+ bfd *output_bfd, char **error_message)
{
if (output_bfd)
{
/* Given a BFD reloc type, return the matching HOWTO structure. */
static reloc_howto_type *
-lookup_howto (rtype)
- unsigned int rtype;
+lookup_howto (unsigned int rtype)
{
static int inited = 0;
int i;
}
static reloc_howto_type*
-elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
- bfd *abfd ATTRIBUTE_UNUSED;
- bfd_reloc_code_real_type bfd_code;
+elfNN_ia64_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ bfd_reloc_code_real_type bfd_code)
{
unsigned int rtype;
return lookup_howto (rtype);
}
+static reloc_howto_type *
+elfNN_ia64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (ia64_howto_table) / sizeof (ia64_howto_table[0]);
+ i++)
+ if (ia64_howto_table[i].name != NULL
+ && strcasecmp (ia64_howto_table[i].name, r_name) == 0)
+ return &ia64_howto_table[i];
+
+ return NULL;
+}
+
/* Given a ELF reloc, return the matching HOWTO structure. */
static void
-elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
- bfd *abfd ATTRIBUTE_UNUSED;
- arelent *bfd_reloc;
- Elf_Internal_Rela *elf_reloc;
+elfNN_ia64_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED,
+ arelent *bfd_reloc,
+ Elf_Internal_Rela *elf_reloc)
{
bfd_reloc->howto
= lookup_howto ((unsigned int) ELFNN_R_TYPE (elf_reloc->r_info));
/* It should never happen. */
abort ();
}
-
+
/* We can turn br.cond/br.call into brl.cond/brl.call. */
if (!(IS_BR_COND (br_code) || IS_BR_CALL (br_code)))
return FALSE;
/* These functions do relaxation for IA-64 ELF. */
static bfd_boolean
-elfNN_ia64_relax_section (abfd, sec, link_info, again)
- bfd *abfd;
- asection *sec;
- struct bfd_link_info *link_info;
- bfd_boolean *again;
+elfNN_ia64_relax_section (bfd *abfd, asection *sec,
+ struct bfd_link_info *link_info,
+ bfd_boolean *again)
{
struct one_fixup
{
#undef skip_relax_pass_1
static void
-elfNN_ia64_relax_ldxmov (contents, off)
- bfd_byte *contents;
- bfd_vma off;
+elfNN_ia64_relax_ldxmov (bfd_byte *contents, bfd_vma off)
{
int shift, r1, r3;
bfd_vma dword, insn;
/* Return TRUE if NAME is an unwind table section name. */
static inline bfd_boolean
-is_unwind_section_name (abfd, name)
- bfd *abfd;
- const char *name;
+is_unwind_section_name (bfd *abfd, const char *name)
{
- size_t len1, len2, len3;
-
if (elfNN_ia64_hpux_vec (abfd->xvec)
&& !strcmp (name, ELF_STRING_ia64_unwind_hdr))
return FALSE;
- len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
- len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
- len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
- return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
- && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
- || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
+ return ((CONST_STRNEQ (name, ELF_STRING_ia64_unwind)
+ && ! CONST_STRNEQ (name, ELF_STRING_ia64_unwind_info))
+ || CONST_STRNEQ (name, ELF_STRING_ia64_unwind_once));
}
/* Handle an IA-64 specific section when reading an object file. This
flag. */
static bfd_boolean
-elfNN_ia64_section_flags (flags, hdr)
- flagword *flags;
- const Elf_Internal_Shdr *hdr;
+elfNN_ia64_section_flags (flagword *flags,
+ const Elf_Internal_Shdr *hdr)
{
if (hdr->sh_flags & SHF_IA_64_SHORT)
*flags |= SEC_SMALL_DATA;
section name, which is a hack, but ought to work. */
static bfd_boolean
-elfNN_ia64_fake_sections (abfd, hdr, sec)
- bfd *abfd ATTRIBUTE_UNUSED;
- Elf_Internal_Shdr *hdr;
- asection *sec;
+elfNN_ia64_fake_sections (bfd *abfd, Elf_Internal_Shdr *hdr,
+ asection *sec)
{
register const char *name;
object file. */
static void
-elfNN_ia64_final_write_processing (abfd, linker)
- bfd *abfd;
- bfd_boolean linker ATTRIBUTE_UNUSED;
+elfNN_ia64_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
{
Elf_Internal_Shdr *hdr;
asection *s;
file. We use it to put .comm items in .sbss, and not .bss. */
static bfd_boolean
-elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
- bfd *abfd;
- struct bfd_link_info *info;
- Elf_Internal_Sym *sym;
- const char **namep ATTRIBUTE_UNUSED;
- flagword *flagsp ATTRIBUTE_UNUSED;
- asection **secp;
- bfd_vma *valp;
+elfNN_ia64_add_symbol_hook (bfd *abfd,
+ struct bfd_link_info *info,
+ Elf_Internal_Sym *sym,
+ const char **namep ATTRIBUTE_UNUSED,
+ flagword *flagsp ATTRIBUTE_UNUSED,
+ asection **secp,
+ bfd_vma *valp)
{
if (sym->st_shndx == SHN_COMMON
&& !info->relocatable
}
}
- /* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of
- the input sections for each output section in the segment and testing
- for SHF_IA_64_NORECOV on each. */
- for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+ return TRUE;
+}
+
+/* Turn on PF_IA_64_NORECOV if needed. This involves traversing all of
+ the input sections for each output section in the segment and testing
+ for SHF_IA_64_NORECOV on each. */
+
+static bfd_boolean
+elfNN_ia64_modify_program_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ struct elf_obj_tdata *tdata = elf_tdata (abfd);
+ struct elf_segment_map *m;
+ Elf_Internal_Phdr *p;
+
+ for (p = tdata->phdr, m = tdata->segment_map; m != NULL; m = m->next, p++)
if (m->p_type == PT_LOAD)
{
int i;
for (i = m->count - 1; i >= 0; --i)
{
struct bfd_link_order *order = m->sections[i]->map_head.link_order;
- while (order)
+
+ while (order != NULL)
{
if (order->type == bfd_indirect_link_order)
{
bfd_vma flags = elf_section_data(is)->this_hdr.sh_flags;
if (flags & SHF_IA_64_NORECOV)
{
- m->p_flags |= PF_IA_64_NORECOV;
+ p->p_flags |= PF_IA_64_NORECOV;
goto found;
}
}
'.' are local. */
static bfd_boolean
-elfNN_ia64_is_local_label_name (abfd, name)
- bfd *abfd ATTRIBUTE_UNUSED;
- const char *name;
+elfNN_ia64_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED,
+ const char *name)
{
return name[0] == '.';
}
/* Should we do dynamic things to this symbol? */
static bfd_boolean
-elfNN_ia64_dynamic_symbol_p (h, info, r_type)
- struct elf_link_hash_entry *h;
- struct bfd_link_info *info;
- int r_type;
+elfNN_ia64_dynamic_symbol_p (struct elf_link_hash_entry *h,
+ struct bfd_link_info *info, int r_type)
{
bfd_boolean ignore_protected
= ((r_type & 0xf8) == 0x40 /* FPTR relocs */
}
\f
static struct bfd_hash_entry*
-elfNN_ia64_new_elf_hash_entry (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
+elfNN_ia64_new_elf_hash_entry (struct bfd_hash_entry *entry,
+ struct bfd_hash_table *table,
+ const char *string)
{
struct elfNN_ia64_link_hash_entry *ret;
ret = (struct elfNN_ia64_link_hash_entry *) entry;
}
static void
-elfNN_ia64_hash_copy_indirect (info, xdir, xind)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *xdir, *xind;
+elfNN_ia64_hash_copy_indirect (struct bfd_link_info *info,
+ struct elf_link_hash_entry *xdir,
+ struct elf_link_hash_entry *xind)
{
struct elfNN_ia64_link_hash_entry *dir, *ind;
}
static void
-elfNN_ia64_hash_hide_symbol (info, xh, force_local)
- struct bfd_link_info *info;
- struct elf_link_hash_entry *xh;
- bfd_boolean force_local;
+elfNN_ia64_hash_hide_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *xh,
+ bfd_boolean force_local)
{
struct elfNN_ia64_link_hash_entry *h;
struct elfNN_ia64_dyn_sym_info *dyn_i;
/* Compute a hash of a local hash entry. */
static hashval_t
-elfNN_ia64_local_htab_hash (ptr)
- const void *ptr;
+elfNN_ia64_local_htab_hash (const void *ptr)
{
struct elfNN_ia64_local_hash_entry *entry
= (struct elfNN_ia64_local_hash_entry *) ptr;
/* Compare local hash entries. */
static int
-elfNN_ia64_local_htab_eq (ptr1, ptr2)
- const void *ptr1, *ptr2;
+elfNN_ia64_local_htab_eq (const void *ptr1, const void *ptr2)
{
struct elfNN_ia64_local_hash_entry *entry1
= (struct elfNN_ia64_local_hash_entry *) ptr1;
linker (without using static variables). */
static struct bfd_link_hash_table*
-elfNN_ia64_hash_table_create (abfd)
- bfd *abfd;
+elfNN_ia64_hash_table_create (bfd *abfd)
{
struct elfNN_ia64_link_hash_table *ret;
/* Destroy IA-64 linker hash table. */
static void
-elfNN_ia64_hash_table_free (hash)
- struct bfd_link_hash_table *hash;
+elfNN_ia64_hash_table_free (struct bfd_link_hash_table *hash)
{
struct elfNN_ia64_link_hash_table *ia64_info
= (struct elfNN_ia64_link_hash_table *) hash;
struct elfNN_ia64_dyn_sym_traverse_data
{
- bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
+ bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR);
PTR data;
};
static bfd_boolean
-elfNN_ia64_global_dyn_sym_thunk (xentry, xdata)
- struct bfd_hash_entry *xentry;
- PTR xdata;
+elfNN_ia64_global_dyn_sym_thunk (struct bfd_hash_entry *xentry,
+ PTR xdata)
{
struct elfNN_ia64_link_hash_entry *entry
= (struct elfNN_ia64_link_hash_entry *) xentry;
}
static bfd_boolean
-elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
- void **slot;
- PTR xdata;
+elfNN_ia64_local_dyn_sym_thunk (void **slot, PTR xdata)
{
struct elfNN_ia64_local_hash_entry *entry
= (struct elfNN_ia64_local_hash_entry *) *slot;
}
static void
-elfNN_ia64_dyn_sym_traverse (ia64_info, func, data)
- struct elfNN_ia64_link_hash_table *ia64_info;
- bfd_boolean (*func) PARAMS ((struct elfNN_ia64_dyn_sym_info *, PTR));
- PTR data;
+elfNN_ia64_dyn_sym_traverse (struct elfNN_ia64_link_hash_table *ia64_info,
+ bfd_boolean (*func) (struct elfNN_ia64_dyn_sym_info *, PTR),
+ PTR data)
{
struct elfNN_ia64_dyn_sym_traverse_data xdata;
}
\f
static bfd_boolean
-elfNN_ia64_create_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+elfNN_ia64_create_dynamic_sections (bfd *abfd,
+ struct bfd_link_info *info)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *s;
/* Find and/or create a hash entry for local symbol. */
static struct elfNN_ia64_local_hash_entry *
-get_local_sym_hash (ia64_info, abfd, rel, create)
- struct elfNN_ia64_link_hash_table *ia64_info;
- bfd *abfd;
- const Elf_Internal_Rela *rel;
- bfd_boolean create;
+get_local_sym_hash (struct elfNN_ia64_link_hash_table *ia64_info,
+ bfd *abfd, const Elf_Internal_Rela *rel,
+ bfd_boolean create)
{
struct elfNN_ia64_local_hash_entry e, *ret;
asection *sec = abfd->sections;
const struct elfNN_ia64_dyn_sym_info *y
= (const struct elfNN_ia64_dyn_sym_info *) yp;
- return x->addend - y->addend;
+ return x->addend < y->addend ? -1 : x->addend > y->addend ? 1 : 0;
}
/* Sort elfNN_ia64_dyn_sym_info array and remove duplicates. */
sort_dyn_sym_info (struct elfNN_ia64_dyn_sym_info *info,
unsigned int count)
{
- bfd_vma curr, prev;
- unsigned int i, dup, diff, dest, src, len;
+ bfd_vma curr, prev, got_offset;
+ unsigned int i, kept, dup, diff, dest, src, len;
qsort (info, count, sizeof (*info), addend_compare);
/* Find the first duplicate. */
prev = info [0].addend;
+ got_offset = info [0].got_offset;
for (i = 1; i < count; i++)
{
curr = info [i].addend;
if (curr == prev)
- break;
+ {
+ /* For duplicates, make sure that GOT_OFFSET is valid. */
+ if (got_offset == (bfd_vma) -1)
+ got_offset = info [i].got_offset;
+ break;
+ }
+ got_offset = info [i].got_offset;
prev = curr;
}
+ /* We may move a block of elements to here. */
+ dest = i++;
+
/* Remove duplicates. */
if (i < count)
{
- /* We need to move a block of elements to here. */
- dest = i++;
while (i < count)
{
+ /* For duplicates, make sure that the kept one has a valid
+ got_offset. */
+ kept = dest - 1;
+ if (got_offset != (bfd_vma) -1)
+ info [kept].got_offset = got_offset;
+
curr = info [i].addend;
+ got_offset = info [i].got_offset;
/* Move a block of elements whose first one is different from
the previous. */
if (curr == prev)
{
for (src = i + 1; src < count; src++)
- if (info [src].addend != curr)
- break;
+ {
+ if (info [src].addend != curr)
+ break;
+ /* For duplicates, make sure that GOT_OFFSET is
+ valid. */
+ if (got_offset == (bfd_vma) -1)
+ got_offset = info [src].got_offset;
+ }
+
+ /* Make sure that the kept one has a valid got_offset. */
+ if (got_offset != (bfd_vma) -1)
+ info [kept].got_offset = got_offset;
}
else
src = i;
if (src >= count)
break;
- /* Find the next duplicate. */
+ /* Find the next duplicate. SRC will be kept. */
prev = info [src].addend;
+ got_offset = info [src].got_offset;
for (dup = src + 1; dup < count; dup++)
{
curr = info [dup].addend;
if (curr == prev)
- break;
+ {
+ /* Make sure that got_offset is valid. */
+ if (got_offset == (bfd_vma) -1)
+ got_offset = info [dup].got_offset;
+
+ /* For duplicates, make sure that the kept one has
+ a valid got_offset. */
+ if (got_offset != (bfd_vma) -1)
+ info [dup - 1].got_offset = got_offset;
+ break;
+ }
+ got_offset = info [dup].got_offset;
prev = curr;
}
if (len == 1 && dup < count)
{
/* If we only move 1 element, we combine it with the next
- one. Find the next different one. */
+ one. There must be at least a duplicate. Find the
+ next different one. */
for (diff = dup + 1, src++; diff < count; diff++, src++)
- if (info [diff].addend != curr)
- break;
+ {
+ if (info [diff].addend != curr)
+ break;
+ /* Make sure that got_offset is valid. */
+ if (got_offset == (bfd_vma) -1)
+ got_offset = info [diff].got_offset;
+ }
+
+ /* Makre sure that the last duplicated one has an valid
+ offset. */
+ BFD_ASSERT (curr == prev);
+ if (got_offset != (bfd_vma) -1)
+ info [diff - 1].got_offset = got_offset;
if (diff < count)
{
- /* Find the next duplicate. */
+ /* Find the next duplicate. Track the current valid
+ offset. */
prev = info [diff].addend;
+ got_offset = info [diff].got_offset;
for (dup = diff + 1; dup < count; dup++)
{
curr = info [dup].addend;
if (curr == prev)
- break;
+ {
+ /* For duplicates, make sure that GOT_OFFSET
+ is valid. */
+ if (got_offset == (bfd_vma) -1)
+ got_offset = info [dup].got_offset;
+ break;
+ }
+ got_offset = info [dup].got_offset;
prev = curr;
diff++;
}
count = dest;
}
+ else
+ {
+ /* When we get here, either there is no duplicate at all or
+ the only duplicate is the last element. */
+ if (dest < count)
+ {
+ /* If the last element is a duplicate, make sure that the
+ kept one has a valid got_offset. We also update count. */
+ if (got_offset != (bfd_vma) -1)
+ info [dest - 1].got_offset = got_offset;
+ count = dest;
+ }
+ }
return count;
}
requires a copy which is O(N), but this only happens once. */
static struct elfNN_ia64_dyn_sym_info *
-get_dyn_sym_info (ia64_info, h, abfd, rel, create)
- struct elfNN_ia64_link_hash_table *ia64_info;
- struct elf_link_hash_entry *h;
- bfd *abfd;
- const Elf_Internal_Rela *rel;
- bfd_boolean create;
+get_dyn_sym_info (struct elfNN_ia64_link_hash_table *ia64_info,
+ struct elf_link_hash_entry *h, bfd *abfd,
+ const Elf_Internal_Rela *rel, bfd_boolean create)
{
struct elfNN_ia64_dyn_sym_info **info_p, *info, *dyn_i, key;
unsigned int *count_p, *sorted_count_p, *size_p;
/* Append the new one to the array. */
dyn_i = info + count;
memset (dyn_i, 0, sizeof (*dyn_i));
+ dyn_i->got_offset = (bfd_vma) -1;
dyn_i->addend = addend;
-
+
/* We increment count only since the new ones are unsorted and
may have duplicate. */
(*count_p)++;
}
static asection *
-get_got (abfd, info, ia64_info)
- bfd *abfd;
- struct bfd_link_info *info;
- struct elfNN_ia64_link_hash_table *ia64_info;
+get_got (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_link_hash_table *ia64_info)
{
asection *got;
bfd *dynobj;
of a procedure, thus ensuring a unique address for each procedure. */
static asection *
-get_fptr (abfd, info, ia64_info)
- bfd *abfd;
- struct bfd_link_info *info;
- struct elfNN_ia64_link_hash_table *ia64_info;
+get_fptr (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_link_hash_table *ia64_info)
{
asection *fptr;
bfd *dynobj;
}
static asection *
-get_pltoff (abfd, info, ia64_info)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- struct elfNN_ia64_link_hash_table *ia64_info;
+get_pltoff (bfd *abfd, struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elfNN_ia64_link_hash_table *ia64_info)
{
asection *pltoff;
bfd *dynobj;
}
static asection *
-get_reloc_section (abfd, ia64_info, sec, create)
- bfd *abfd;
- struct elfNN_ia64_link_hash_table *ia64_info;
- asection *sec;
- bfd_boolean create;
+get_reloc_section (bfd *abfd,
+ struct elfNN_ia64_link_hash_table *ia64_info,
+ asection *sec, bfd_boolean create)
{
const char *srel_name;
asection *srel;
if (srel_name == NULL)
return NULL;
- BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
+ BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela")
&& strcmp (bfd_get_section_name (abfd, sec),
srel_name+5) == 0)
- || (strncmp (srel_name, ".rel", 4) == 0
+ || (CONST_STRNEQ (srel_name, ".rel")
&& strcmp (bfd_get_section_name (abfd, sec),
srel_name+4) == 0));
}
static bfd_boolean
-elfNN_ia64_check_relocs (abfd, info, sec, relocs)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- const Elf_Internal_Rela *relocs;
+elfNN_ia64_check_relocs (bfd *abfd, struct bfd_link_info *info,
+ asection *sec,
+ const Elf_Internal_Rela *relocs)
{
struct elfNN_ia64_link_hash_table *ia64_info;
const Elf_Internal_Rela *relend;
have yet been processed. Do something with what we know, as
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
- && (!info->symbolic
+ && (!SYMBOLIC_BIND (info, h)
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->def_regular
|| h->root.type == bfd_link_hash_defweak));
}
/* Now, we only do lookup without insertion, which is very fast
- with the modified get_dyn_sym_info. */
+ with the modified get_dyn_sym_info. */
for (rel = relocs; rel < relend; ++rel)
{
struct elfNN_ia64_dyn_sym_info *dyn_i;
have yet been processed. Do something with what we know, as
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
- && (!info->symbolic
+ && (!SYMBOLIC_BIND (info, h)
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->def_regular
|| h->root.type == bfd_link_hash_defweak));
external GOT entries first. */
static bfd_boolean
-allocate_global_data_got (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_global_data_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
/* Next, allocate all the GOT entries used by LTOFF_FPTR relocs. */
static bfd_boolean
-allocate_global_fptr_got (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_global_fptr_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
/* Lastly, allocate all the GOT entries for local data. */
static bfd_boolean
-allocate_local_got (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_local_got (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
/* Search for the index of a global symbol in it's defining object file. */
static long
-global_sym_index (h)
- struct elf_link_hash_entry *h;
+global_sym_index (struct elf_link_hash_entry *h)
{
struct elf_link_hash_entry **p;
bfd *obj;
in a main executable that is not exported. */
static bfd_boolean
-allocate_fptr (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_fptr (struct elfNN_ia64_dyn_sym_info *dyn_i, PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
/* Allocate all the minimal PLT entries. */
static bfd_boolean
-allocate_plt_entries (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_plt_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
/* Allocate all the full PLT entries. */
static bfd_boolean
-allocate_plt2_entries (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_plt2_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
??? Relaxation might be able to determine that they are. */
static bfd_boolean
-allocate_pltoff_entries (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_pltoff_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
to be dynamic. */
static bfd_boolean
-allocate_dynrel_entries (dyn_i, data)
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- PTR data;
+allocate_dynrel_entries (struct elfNN_ia64_dyn_sym_info *dyn_i,
+ PTR data)
{
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
struct elfNN_ia64_link_hash_table *ia64_info;
}
static bfd_boolean
-elfNN_ia64_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
- struct elf_link_hash_entry *h;
+elfNN_ia64_adjust_dynamic_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h)
{
/* ??? Undefined symbols with PLT entries should be re-defined
to be the PLT entry. */
}
static bfd_boolean
-elfNN_ia64_size_dynamic_sections (output_bfd, info)
- bfd *output_bfd ATTRIBUTE_UNUSED;
- struct bfd_link_info *info;
+elfNN_ia64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
+ struct bfd_link_info *info)
{
struct elfNN_ia64_allocate_data data;
struct elfNN_ia64_link_hash_table *ia64_info;
if (strcmp (name, ".got.plt") == 0)
strip = FALSE;
- else if (strncmp (name, ".rel", 4) == 0)
+ else if (CONST_STRNEQ (name, ".rel"))
{
if (!strip)
{
}
static bfd_reloc_status_type
-elfNN_ia64_install_value (hit_addr, v, r_type)
- bfd_byte *hit_addr;
- bfd_vma v;
- unsigned int r_type;
+elfNN_ia64_install_value (bfd_byte *hit_addr, bfd_vma v,
+ unsigned int r_type)
{
const struct ia64_operand *op;
int bigendian = 0, shift = 0;
}
static void
-elfNN_ia64_install_dyn_reloc (abfd, info, sec, srel, offset, type,
- dynindx, addend)
- bfd *abfd;
- struct bfd_link_info *info;
- asection *sec;
- asection *srel;
- bfd_vma offset;
- unsigned int type;
- long dynindx;
- bfd_vma addend;
+elfNN_ia64_install_dyn_reloc (bfd *abfd, struct bfd_link_info *info,
+ asection *sec, asection *srel,
+ bfd_vma offset, unsigned int type,
+ long dynindx, bfd_vma addend)
{
Elf_Internal_Rela outrel;
bfd_byte *loc;
and return the gp-relative address of the linkage table entry. */
static bfd_vma
-set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
- bfd *abfd;
- struct bfd_link_info *info;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- long dynindx;
- bfd_vma addend;
- bfd_vma value;
- unsigned int dyn_r_type;
+set_got_entry (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_dyn_sym_info *dyn_i,
+ long dynindx, bfd_vma addend, bfd_vma value,
+ unsigned int dyn_r_type)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *got_sec;
address and its global pointer. Return the descriptor's address. */
static bfd_vma
-set_fptr_entry (abfd, info, dyn_i, value)
- bfd *abfd;
- struct bfd_link_info *info;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- bfd_vma value;
+set_fptr_entry (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_dyn_sym_info *dyn_i,
+ bfd_vma value)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *fptr_sec;
and its global pointer. Return the descriptor's address. */
static bfd_vma
-set_pltoff_entry (abfd, info, dyn_i, value, is_plt)
- bfd *abfd;
- struct bfd_link_info *info;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- bfd_vma value;
- bfd_boolean is_plt;
+set_pltoff_entry (bfd *abfd, struct bfd_link_info *info,
+ struct elfNN_ia64_dyn_sym_info *dyn_i,
+ bfd_vma value, bfd_boolean is_plt)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *pltoff_sec;
is assigned offset round(2 * size of pointer, PT_TLS p_align). */
static bfd_vma
-elfNN_ia64_tprel_base (info)
- struct bfd_link_info *info;
+elfNN_ia64_tprel_base (struct bfd_link_info *info)
{
asection *tls_sec = elf_hash_table (info)->tls_sec;
-
- BFD_ASSERT (tls_sec != NULL);
return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
tls_sec->alignment_power);
}
This is PT_TLS segment p_vaddr. */
static bfd_vma
-elfNN_ia64_dtprel_base (info)
- struct bfd_link_info *info;
+elfNN_ia64_dtprel_base (struct bfd_link_info *info)
{
- BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
return elf_hash_table (info)->tls_sec->vma;
}
static bfd *elfNN_ia64_unwind_entry_compare_bfd;
static int
-elfNN_ia64_unwind_entry_compare (a, b)
- const PTR a;
- const PTR b;
+elfNN_ia64_unwind_entry_compare (const PTR a, const PTR b)
{
bfd_vma av, bv;
/* Make sure we've got ourselves a nice fat __gp value. */
static bfd_boolean
-elfNN_ia64_choose_gp (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+elfNN_ia64_choose_gp (bfd *abfd, struct bfd_link_info *info)
{
bfd_vma min_vma = (bfd_vma) -1, max_vma = 0;
bfd_vma min_short_vma = min_vma, max_short_vma = 0;
continue;
lo = os->vma;
- hi = os->vma + os->size;
+ hi = os->vma + (os->rawsize ? os->rawsize : os->size);
if (hi < lo)
hi = (bfd_vma) -1;
}
static bfd_boolean
-elfNN_ia64_final_link (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+elfNN_ia64_final_link (bfd *abfd, struct bfd_link_info *info)
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *unwind_output_sec;
}
static bfd_boolean
-elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
- contents, relocs, local_syms, local_sections)
- bfd *output_bfd;
- struct bfd_link_info *info;
- bfd *input_bfd;
- asection *input_section;
- bfd_byte *contents;
- Elf_Internal_Rela *relocs;
- Elf_Internal_Sym *local_syms;
- asection **local_sections;
+elfNN_ia64_relocate_section (bfd *output_bfd,
+ struct bfd_link_info *info,
+ bfd *input_bfd,
+ asection *input_section,
+ bfd_byte *contents,
+ Elf_Internal_Rela *relocs,
+ Elf_Internal_Sym *local_syms,
+ asection **local_sections)
{
struct elfNN_ia64_link_hash_table *ia64_info;
Elf_Internal_Shdr *symtab_hdr;
elf_section_data(input_section->output_section)
->this_hdr.sh_flags |= flags;
- return TRUE;
}
gp_val = _bfd_get_gp_value (output_bfd);
sym_sec = local_sections[r_symndx];
msec = sym_sec;
value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
- if ((sym_sec->flags & SEC_MERGE)
+ if (!info->relocatable
+ && (sym_sec->flags & SEC_MERGE) != 0
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
- sym_sec->output_section->vma
- sym_sec->output_offset;
}
-
- qsort (loc_h->info, loc_h->count,
- sizeof (*loc_h->info), addend_compare);
+
+ /* We may have introduced duplicated entries. We need
+ to remove them properly. */
+ count = sort_dyn_sym_info (loc_h->info, loc_h->count);
+ if (count != loc_h->count)
+ {
+ loc_h->count = count;
+ loc_h->sorted_count = count;
+ }
loc_h->sec_merge_done = 1;
}
continue;
}
+ /* For relocs against symbols from removed linkonce sections,
+ or sections discarded by a linker script, we just want the
+ section contents zeroed. Avoid any special processing. */
+ if (sym_sec != NULL && elf_discarded_section (sym_sec))
+ {
+ _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset);
+ rel->r_info = 0;
+ rel->r_addend = 0;
+ continue;
+ }
+
+ if (info->relocatable)
+ continue;
+
hit_addr = contents + rel->r_offset;
value += rel->r_addend;
dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info, r_type);
case R_IA64_SEGREL32LSB:
case R_IA64_SEGREL64MSB:
case R_IA64_SEGREL64LSB:
- if (r_symndx == 0)
- {
- /* If the input section was discarded from the output, then
- do nothing. */
- r = bfd_reloc_ok;
- }
- else
{
- struct elf_segment_map *m;
- Elf_Internal_Phdr *p;
-
/* Find the segment that contains the output_section. */
- for (m = elf_tdata (output_bfd)->segment_map,
- p = elf_tdata (output_bfd)->phdr;
- m != NULL;
- m = m->next, p++)
- {
- int i;
- for (i = m->count - 1; i >= 0; i--)
- if (m->sections[i] == input_section->output_section)
- break;
- if (i >= 0)
- break;
- }
+ Elf_Internal_Phdr *p = _bfd_elf_find_segment_containing_section
+ (output_bfd, input_section->output_section);
- if (m == NULL)
+ if (p == NULL)
{
r = bfd_reloc_notsupported;
}
case R_IA64_TPREL14:
case R_IA64_TPREL22:
case R_IA64_TPREL64I:
+ if (elf_hash_table (info)->tls_sec == NULL)
+ goto missing_tls_sec;
value -= elfNN_ia64_tprel_base (info);
r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_DTPREL32MSB:
case R_IA64_DTPREL64LSB:
case R_IA64_DTPREL64MSB:
+ if (elf_hash_table (info)->tls_sec == NULL)
+ goto missing_tls_sec;
value -= elfNN_ia64_dtprel_base (info);
r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF_TPREL22:
if (!dynamic_symbol_p)
{
+ if (elf_hash_table (info)->tls_sec == NULL)
+ goto missing_tls_sec;
if (!info->shared)
value -= elfNN_ia64_tprel_base (info);
else
break;
case R_IA64_LTOFF_DTPREL22:
if (!dynamic_symbol_p)
- value -= elfNN_ia64_dtprel_base (info);
+ {
+ if (elf_hash_table (info)->tls_sec == NULL)
+ goto missing_tls_sec;
+ value -= elfNN_ia64_dtprel_base (info);
+ }
got_r_type = R_IA64_DTPRELNNLSB;
break;
}
case bfd_reloc_outofrange:
case bfd_reloc_overflow:
default:
+missing_tls_sec:
{
const char *name;
switch (r_type)
{
+ case R_IA64_TPREL14:
+ case R_IA64_TPREL22:
+ case R_IA64_TPREL64I:
+ case R_IA64_DTPREL14:
+ case R_IA64_DTPREL22:
+ case R_IA64_DTPREL64I:
+ case R_IA64_DTPREL32LSB:
+ case R_IA64_DTPREL32MSB:
+ case R_IA64_DTPREL64LSB:
+ case R_IA64_DTPREL64MSB:
+ case R_IA64_LTOFF_TPREL22:
+ case R_IA64_LTOFF_DTPMOD22:
+ case R_IA64_LTOFF_DTPREL22:
+ (*_bfd_error_handler)
+ (_("%B: missing TLS section for relocation %s against `%s' at 0x%lx in section `%A'."),
+ input_bfd, input_section, howto->name, name,
+ rel->r_offset);
+ break;
+
case R_IA64_PCREL21B:
case R_IA64_PCREL21BI:
case R_IA64_PCREL21M:
}
static bfd_boolean
-elfNN_ia64_finish_dynamic_symbol (output_bfd, info, h, sym)
- bfd *output_bfd;
- struct bfd_link_info *info;
- struct elf_link_hash_entry *h;
- Elf_Internal_Sym *sym;
+elfNN_ia64_finish_dynamic_symbol (bfd *output_bfd,
+ struct bfd_link_info *info,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
struct elfNN_ia64_link_hash_table *ia64_info;
struct elfNN_ia64_dyn_sym_info *dyn_i;
}
static bfd_boolean
-elfNN_ia64_finish_dynamic_sections (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info;
+elfNN_ia64_finish_dynamic_sections (bfd *abfd,
+ struct bfd_link_info *info)
{
struct elfNN_ia64_link_hash_table *ia64_info;
bfd *dynobj;
/* Function to keep IA-64 specific file flags. */
static bfd_boolean
-elfNN_ia64_set_private_flags (abfd, flags)
- bfd *abfd;
- flagword flags;
+elfNN_ia64_set_private_flags (bfd *abfd, flagword flags)
{
BFD_ASSERT (!elf_flags_init (abfd)
|| elf_elfheader (abfd)->e_flags == flags);
/* Merge backend specific data from an object file to the output
object file when linking. */
static bfd_boolean
-elfNN_ia64_merge_private_bfd_data (ibfd, obfd)
- bfd *ibfd, *obfd;
+elfNN_ia64_merge_private_bfd_data (bfd *ibfd, bfd *obfd)
{
flagword out_flags;
flagword in_flags;
}
static bfd_boolean
-elfNN_ia64_print_private_bfd_data (abfd, ptr)
- bfd *abfd;
- PTR ptr;
+elfNN_ia64_print_private_bfd_data (bfd *abfd, PTR ptr)
{
FILE *file = (FILE *) ptr;
flagword flags = elf_elfheader (abfd)->e_flags;
}
static enum elf_reloc_type_class
-elfNN_ia64_reloc_type_class (rela)
- const Elf_Internal_Rela *rela;
+elfNN_ia64_reloc_type_class (const Elf_Internal_Rela *rela)
{
switch ((int) ELFNN_R_TYPE (rela->r_info))
{
static const struct bfd_elf_special_section elfNN_ia64_special_sections[] =
{
- { ".sbss", 5, -1, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
- { ".sdata", 6, -1, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
- { NULL, 0, 0, 0, 0 }
+ { 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 }
};
static bfd_boolean
if (elf_sec_group (sec) == NULL
&& ((sec->flags & (SEC_LINK_ONCE | SEC_CODE | SEC_GROUP))
== (SEC_LINK_ONCE | SEC_CODE))
- && strncmp (sec->name, ".gnu.linkonce.t.", 16) == 0)
+ && CONST_STRNEQ (sec->name, ".gnu.linkonce.t."))
{
name = sec->name + 16;
}
static void
-elfNN_hpux_post_process_headers (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elfNN_hpux_post_process_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+ i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
i_ehdrp->e_ident[EI_ABIVERSION] = 1;
}
-bfd_boolean
-elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
- bfd *abfd ATTRIBUTE_UNUSED;
- asection *sec;
- int *retval;
+static bfd_boolean
+elfNN_hpux_backend_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED,
+ asection *sec, int *retval)
{
if (bfd_is_com_section (sec))
{
elfNN_ia64_additional_program_headers
#define elf_backend_modify_segment_map \
elfNN_ia64_modify_segment_map
+#define elf_backend_modify_program_headers \
+ elfNN_ia64_modify_program_headers
#define elf_info_to_howto \
elfNN_ia64_info_to_howto
#define bfd_elfNN_bfd_reloc_type_lookup \
elfNN_ia64_reloc_type_lookup
+#define bfd_elfNN_bfd_reloc_name_lookup \
+ elfNN_ia64_reloc_name_lookup
#define bfd_elfNN_bfd_is_local_label_name \
elfNN_ia64_is_local_label_name
#define bfd_elfNN_bfd_relax_section \
elfNN_ia64_adjust_dynamic_symbol
#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)
#define elf_backend_relocate_section \
elfNN_ia64_relocate_section
#define elf_backend_finish_dynamic_symbol \
#define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
#define elf_backend_rela_normal 1
#define elf_backend_special_sections elfNN_ia64_special_sections
+#define elf_backend_default_execstack 0
/* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
SHF_LINK_ORDER. But it doesn't set the sh_link or sh_info fields.
#undef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 1
-#undef ELF_MAXPAGESIZE
-#define ELF_MAXPAGESIZE 0x1000 /* 4K */
#undef ELF_COMMONPAGESIZE
+#undef ELF_OSABI
+#define ELF_OSABI ELFOSABI_HPUX
#undef elfNN_bed
#define elfNN_bed elfNN_ia64_hpux_bed