#include "elf-bfd.h"
#include "opcode/ia64.h"
#include "elf/ia64.h"
+#include "objalloc.h"
+#include "hashtab.h"
/* THE RULES for all the stuff the linker creates --
descriptor for a MIN_PLT entry, and requires one IPLT reloc.
MIN_PLT Created by PLTOFF entries against dynamic symbols. This
- does not reqire dynamic relocations. */
+ does not require dynamic relocations. */
#define NELEMS(a) ((int) (sizeof (a) / sizeof ((a)[0])))
bfd_vma dtpmod_offset;
bfd_vma dtprel_offset;
- /* The symbol table entry, if any, that this was derrived from. */
+ /* The symbol table entry, if any, that this was derived from. */
struct elf_link_hash_entry *h;
/* Used to count non-got, non-plt relocations for delayed sizing
asection *srel;
int type;
int count;
+
+ /* Is this reloc against readonly section? */
+ bfd_boolean reltext;
} *reloc_entries;
/* TRUE when the section contents have been updated. */
struct elfNN_ia64_local_hash_entry
{
- struct bfd_hash_entry root;
+ int id;
+ unsigned int r_sym;
struct elfNN_ia64_dyn_sym_info *info;
/* TRUE if this hash entry's addends was translated for
unsigned sec_merge_done : 1;
};
-struct elfNN_ia64_local_hash_table
-{
- struct bfd_hash_table root;
- /* No additional fields for now. */
-};
-
struct elfNN_ia64_link_hash_entry
{
struct elf_link_hash_entry root;
unsigned self_dtpmod_done : 1;/* has self DTPMOD entry been finished? */
bfd_vma self_dtpmod_offset; /* .got offset to self DTPMOD entry */
- struct elfNN_ia64_local_hash_table loc_hash_table;
+ htab_t loc_hash_table;
+ void *loc_hash_memory;
};
struct elfNN_ia64_allocate_data
static int elfNN_ia64_additional_program_headers
PARAMS ((bfd *abfd));
static bfd_boolean elfNN_ia64_modify_segment_map
- PARAMS ((bfd *));
+ PARAMS ((bfd *, struct bfd_link_info *));
static bfd_boolean elfNN_ia64_is_local_label_name
PARAMS ((bfd *abfd, const char *name));
static bfd_boolean elfNN_ia64_dynamic_symbol_p
PARAMS ((struct elf_link_hash_entry *h, struct bfd_link_info *info, int));
-static bfd_boolean elfNN_ia64_local_hash_table_init
- PARAMS ((struct elfNN_ia64_local_hash_table *ht, bfd *abfd,
- new_hash_entry_func new));
-static struct bfd_hash_entry *elfNN_ia64_new_loc_hash_entry
- PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
- const char *string));
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));
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 struct elfNN_ia64_local_hash_entry *elfNN_ia64_local_hash_lookup
- PARAMS ((struct elfNN_ia64_local_hash_table *table, const char *string,
- bfd_boolean create, bfd_boolean copy));
+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 bfd_boolean elfNN_ia64_local_dyn_sym_thunk
- PARAMS ((struct bfd_hash_entry *, PTR));
+static int elfNN_ia64_local_dyn_sym_thunk
+ PARAMS ((void **, PTR));
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),
static asection *get_reloc_section
PARAMS ((bfd *abfd, struct elfNN_ia64_link_hash_table *ia64_info,
asection *sec, bfd_boolean create));
-static bfd_boolean count_dyn_reloc
- PARAMS ((bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
- asection *srel, int type));
static bfd_boolean elfNN_ia64_check_relocs
PARAMS ((bfd *abfd, struct bfd_link_info *info, asection *sec,
const Elf_Internal_Rela *relocs));
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 */
+ 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;; */
+};
+
+static size_t oor_branch_size = sizeof (oor_brl);
+
+void
+bfd_elfNN_ia64_after_parse (int itanium)
+{
+ oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
+}
+
+static void
+elfNN_ia64_relax_brl (bfd *abfd, bfd_byte *contents, bfd_vma off)
+{
+ int template;
+ bfd_byte *hit_addr;
+ bfd_vma t0, t1, i0, i1, i2;
+
+ hit_addr = (bfd_byte *) (contents + off);
+ hit_addr -= (long) hit_addr & 0x3;
+ t0 = bfd_get_64 (abfd, hit_addr);
+ t1 = bfd_get_64 (abfd, hit_addr + 8);
+
+ /* Keep the instruction in slot 0. */
+ i0 = (t0 >> 5) & 0x1ffffffffffLL;
+ /* Use nop.b for slot 1. */
+ i1 = 0x4000000000LL;
+ /* For slot 2, turn brl into br by masking out bit 40. */
+ i2 = (t1 >> 23) & 0x0ffffffffffLL;
+
+ /* Turn a MLX bundle into a MBB bundle with the same stop-bit
+ variety. */
+ template = 0x12;
+ if ((t0 & 0x1fLL) == 5)
+ template += 1;
+ t0 = (i1 << 46) | (i0 << 5) | template;
+ t1 = (i2 << 23) | (i1 >> 18);
+
+ bfd_put_64 (abfd, t0, hit_addr);
+ bfd_put_64 (abfd, t1, hit_addr + 8);
+}
\f
/* These functions do relaxation for IA-64 ELF. */
*again = FALSE;
/* Don't even try to relax for non-ELF outputs. */
- if (link_info->hash->creator->flavour != bfd_target_elf_flavour)
+ if (!is_elf_hash_table (link_info->hash))
return FALSE;
/* Nothing to do if there are no relocations or there is no need for
the relax finalize pass. */
if ((sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
- || (link_info->relax_finalizing
+ || (!link_info->need_relax_finalize
&& sec->need_finalize_relax == 0))
return TRUE;
case R_IA64_PCREL21BI:
case R_IA64_PCREL21M:
case R_IA64_PCREL21F:
- if (link_info->relax_finalizing)
+ /* In the finalize pass, all br relaxations are done. We can
+ skip it. */
+ if (!link_info->need_relax_finalize)
continue;
is_branch = TRUE;
break;
+ case R_IA64_PCREL60B:
+ /* We can't optimize brl to br before the finalize pass since
+ br relaxations will increase the code size. Defer it to
+ the finalize pass. */
+ if (link_info->need_relax_finalize)
+ {
+ sec->need_finalize_relax = 1;
+ continue;
+ }
+ is_branch = TRUE;
+ break;
+
case R_IA64_LTOFF22X:
case R_IA64_LDXMOV:
- if (!link_info->relax_finalizing)
+ /* We can't relax ldx/mov before the finalize pass since
+ br relaxations will increase the code size. Defer it to
+ the finalize pass. */
+ if (link_info->need_relax_finalize)
{
sec->need_finalize_relax = 1;
continue;
isym = isymbuf + ELFNN_R_SYM (irel->r_info);
if (isym->st_shndx == SHN_UNDEF)
- continue; /* We can't do anthing with undefined symbols. */
+ continue; /* We can't do anything with undefined symbols. */
else if (isym->st_shndx == SHN_ABS)
tsec = bfd_abs_section_ptr;
else if (isym->st_shndx == SHN_COMMON)
else
{
- /* We can't do anthing with undefined symbols. */
+ /* We can't do anything with undefined symbols. */
if (h->root.type == bfd_link_hash_undefined
|| h->root.type == bfd_link_hash_undefweak)
continue;
if (is_branch)
{
+ bfd_signed_vma offset;
+
reladdr = (sec->output_section->vma
+ sec->output_offset
+ roff) & (bfd_vma) -4;
/* If the branch is in range, no need to do anything. */
if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
&& (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
+ {
+ /* If the 60-bit branch is in 21-bit range, optimize it. */
+ if (r_type == R_IA64_PCREL60B)
+ {
+ elfNN_ia64_relax_brl (abfd, contents, roff);
+
+ irel->r_info
+ = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
+ R_IA64_PCREL21B);
+
+ /* If the original relocation offset points to slot
+ 1, change it to slot 2. */
+ if ((irel->r_offset & 3) == 1)
+ irel->r_offset += 1;
+ }
+
+ continue;
+ }
+ else if (r_type == R_IA64_PCREL60B)
continue;
/* If the branch and target are in the same section, you've
if (tsec == ia64_info->plt_sec)
size = sizeof (plt_full_entry);
else
- {
- size = sizeof (oor_brl);
- }
+ size = oor_branch_size;
/* Resize the current section to make room for the new branch. */
trampoff = (sec->_cooked_size + 15) & (bfd_vma) -16;
+
+ /* If trampoline is out of range, there is nothing we
+ can do. */
+ offset = trampoff - (roff & (bfd_vma) -4);
+ if (offset < -0x1000000 || offset > 0x0FFFFF0)
+ continue;
+
amt = trampoff + size;
contents = (bfd_byte *) bfd_realloc (contents, amt);
if (contents == NULL)
}
else
{
- memcpy (contents + trampoff, oor_brl, size);
- irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
- R_IA64_PCREL60B);
- irel->r_offset = trampoff + 2;
+ if (size == sizeof (oor_ip))
+ {
+ memcpy (contents + trampoff, oor_ip, size);
+ irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
+ R_IA64_PCREL64I);
+ irel->r_addend -= 16;
+ irel->r_offset = trampoff + 2;
+ }
+ else
+ {
+ memcpy (contents + trampoff, oor_brl, size);
+ irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
+ R_IA64_PCREL60B);
+ irel->r_offset = trampoff + 2;
+ }
+
}
/* Record the fixup so we don't do it again this section. */
}
else
{
+ /* If trampoline is out of range, there is nothing we
+ can do. */
+ offset = f->trampoff - (roff & (bfd_vma) -4);
+ if (offset < -0x1000000 || offset > 0x0FFFFF0)
+ continue;
+
/* Nop out the reloc, since we're finalizing things here. */
irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
}
- /* Fix up the existing branch to hit the trampoline. Hope like
- hell this doesn't overflow too. */
- if (elfNN_ia64_install_value (abfd, contents + roff,
- f->trampoff - (roff & (bfd_vma) -4),
+ /* Fix up the existing branch to hit the trampoline. */
+ if (elfNN_ia64_install_value (abfd, contents + roff, offset,
r_type) != bfd_reloc_ok)
goto error_return;
/* ??? Resize .rela.got too. */
}
- if (link_info->relax_finalizing)
+ if (!link_info->need_relax_finalize)
sec->need_finalize_relax = 0;
*again = changed_contents || changed_relocs;
}
static bfd_boolean
-elfNN_ia64_modify_segment_map (abfd)
+elfNN_ia64_modify_segment_map (abfd, info)
bfd *abfd;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
{
struct elf_segment_map *m, **pm;
Elf_Internal_Shdr *hdr;
return _bfd_elf_dynamic_symbol_p (h, info, ignore_protected);
}
\f
-static bfd_boolean
-elfNN_ia64_local_hash_table_init (ht, abfd, new)
- struct elfNN_ia64_local_hash_table *ht;
- bfd *abfd ATTRIBUTE_UNUSED;
- new_hash_entry_func new;
-{
- memset (ht, 0, sizeof (*ht));
- return bfd_hash_table_init (&ht->root, new);
-}
-
-static struct bfd_hash_entry*
-elfNN_ia64_new_loc_hash_entry (entry, table, string)
- struct bfd_hash_entry *entry;
- struct bfd_hash_table *table;
- const char *string;
-{
- struct elfNN_ia64_local_hash_entry *ret;
- ret = (struct elfNN_ia64_local_hash_entry *) entry;
-
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (!ret)
- ret = bfd_hash_allocate (table, sizeof (*ret));
-
- if (!ret)
- return 0;
-
- /* Initialize our local data. All zeros, and definitely easier
- than setting a handful of bit fields. */
- memset (ret, 0, sizeof (*ret));
-
- /* Call the allocation method of the superclass. */
- ret = ((struct elfNN_ia64_local_hash_entry *)
- bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
-
- return (struct bfd_hash_entry *) ret;
-}
-
static struct bfd_hash_entry*
elfNN_ia64_new_elf_hash_entry (entry, table, string)
struct bfd_hash_entry *entry;
(ind->root.elf_link_hash_flags
& (ELF_LINK_HASH_REF_DYNAMIC
| ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+ | ELF_LINK_HASH_REF_REGULAR_NONWEAK
+ | ELF_LINK_HASH_NEEDS_PLT));
if (ind->root.root.type != bfd_link_hash_indirect)
return;
}
}
+/* Compute a hash of a local hash entry. */
+
+static hashval_t
+elfNN_ia64_local_htab_hash (ptr)
+ const void *ptr;
+{
+ struct elfNN_ia64_local_hash_entry *entry
+ = (struct elfNN_ia64_local_hash_entry *) ptr;
+
+ return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8))
+ ^ entry->r_sym ^ (entry->id >> 16);
+}
+
+/* Compare local hash entries. */
+
+static int
+elfNN_ia64_local_htab_eq (ptr1, ptr2)
+ const void *ptr1, *ptr2;
+{
+ struct elfNN_ia64_local_hash_entry *entry1
+ = (struct elfNN_ia64_local_hash_entry *) ptr1;
+ struct elfNN_ia64_local_hash_entry *entry2
+ = (struct elfNN_ia64_local_hash_entry *) ptr2;
+
+ return entry1->id == entry2->id && entry1->r_sym == entry2->r_sym;
+}
+
/* Create the derived linker hash table. The IA-64 ELF port uses this
derived hash table to keep information specific to the IA-64 ElF
linker (without using static variables). */
return 0;
}
- if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
- elfNN_ia64_new_loc_hash_entry))
+ ret->loc_hash_table = htab_try_create (1024, elfNN_ia64_local_htab_hash,
+ elfNN_ia64_local_htab_eq, NULL);
+ ret->loc_hash_memory = objalloc_create ();
+ if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
free (ret);
return 0;
return &ret->root.root;
}
-/* Look up an entry in a Alpha ELF linker hash table. */
+/* Destroy IA-64 linker hash table. */
-static INLINE struct elfNN_ia64_local_hash_entry *
-elfNN_ia64_local_hash_lookup(table, string, create, copy)
- struct elfNN_ia64_local_hash_table *table;
- const char *string;
- bfd_boolean create, copy;
+static void
+elfNN_ia64_hash_table_free (hash)
+ struct bfd_link_hash_table *hash;
{
- return ((struct elfNN_ia64_local_hash_entry *)
- bfd_hash_lookup (&table->root, string, create, copy));
+ struct elfNN_ia64_link_hash_table *ia64_info
+ = (struct elfNN_ia64_link_hash_table *) hash;
+ if (ia64_info->loc_hash_table)
+ htab_delete (ia64_info->loc_hash_table);
+ if (ia64_info->loc_hash_memory)
+ objalloc_free ((struct objalloc *) ia64_info->loc_hash_memory);
+ _bfd_generic_link_hash_table_free (hash);
}
/* Traverse both local and global hash tables. */
}
static bfd_boolean
-elfNN_ia64_local_dyn_sym_thunk (xentry, xdata)
- struct bfd_hash_entry *xentry;
+elfNN_ia64_local_dyn_sym_thunk (slot, xdata)
+ void **slot;
PTR xdata;
{
struct elfNN_ia64_local_hash_entry *entry
- = (struct elfNN_ia64_local_hash_entry *) xentry;
+ = (struct elfNN_ia64_local_hash_entry *) *slot;
struct elfNN_ia64_dyn_sym_traverse_data *data
= (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
struct elfNN_ia64_dyn_sym_info *dyn_i;
for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
if (! (*data->func) (dyn_i, data->data))
- return FALSE;
- return TRUE;
+ return 0;
+ return 1;
}
static void
elf_link_hash_traverse (&ia64_info->root,
elfNN_ia64_global_dyn_sym_thunk, &xdata);
- bfd_hash_traverse (&ia64_info->loc_hash_table.root,
- elfNN_ia64_local_dyn_sym_thunk, &xdata);
+ htab_traverse (ia64_info->loc_hash_table,
+ elfNN_ia64_local_dyn_sym_thunk, &xdata);
}
\f
static bfd_boolean
const Elf_Internal_Rela *rel;
bfd_boolean create;
{
- struct elfNN_ia64_local_hash_entry *ret;
+ struct elfNN_ia64_local_hash_entry e, *ret;
asection *sec = abfd->sections;
- char addr_name [34];
+ hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8))
+ ^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16);
+ void **slot;
- BFD_ASSERT ((sizeof (sec->id)*2 + 1 + sizeof (unsigned long)*2 + 1) <= 34);
- BFD_ASSERT (sec);
+ e.id = sec->id;
+ e.r_sym = ELFNN_R_SYM (rel->r_info);
+ slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
+ create ? INSERT : NO_INSERT);
- /* Construct a string for use in the elfNN_ia64_local_hash_table.
- name describes what was once anonymous memory. */
+ if (!slot)
+ return NULL;
- sprintf (addr_name, "%x:%lx",
- sec->id, (unsigned long) ELFNN_R_SYM (rel->r_info));
+ if (*slot)
+ return (struct elfNN_ia64_local_hash_entry *) *slot;
- /* Collect the canonical entry data for this address. */
- ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
- addr_name, create, create);
+ ret = (struct elfNN_ia64_local_hash_entry *)
+ objalloc_alloc ((struct objalloc *) ia64_info->loc_hash_memory,
+ sizeof (struct elfNN_ia64_local_hash_entry));
+ if (ret)
+ {
+ memset (ret, 0, sizeof (*ret));
+ ret->id = sec->id;
+ ret->r_sym = ELFNN_R_SYM (rel->r_info);
+ *slot = ret;
+ }
return ret;
}
}
/* Create function descriptor section (.opd). This section is called .opd
- because it contains "official prodecure descriptors". The "official"
+ because it contains "official procedure descriptors". The "official"
refers to the fact that these descriptors are used when taking the address
of a procedure, thus ensuring a unique address for each procedure. */
if (info->pie)
{
asection *fptr_rel;
- fptr_rel = bfd_make_section(abfd, ".rela.opd");
+ fptr_rel = bfd_make_section(dynobj, ".rela.opd");
if (fptr_rel == NULL
- || !bfd_set_section_flags (abfd, fptr_rel,
+ || !bfd_set_section_flags (dynobj, fptr_rel,
(SEC_ALLOC | SEC_LOAD
| SEC_HAS_CONTENTS
| SEC_IN_MEMORY
return NULL;
}
- if (sec->flags & SEC_READONLY)
- ia64_info->reltext = 1;
-
return srel;
}
static bfd_boolean
-count_dyn_reloc (abfd, dyn_i, srel, type)
- bfd *abfd;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- asection *srel;
- int type;
+count_dyn_reloc (bfd *abfd, struct elfNN_ia64_dyn_sym_info *dyn_i,
+ asection *srel, int type, bfd_boolean reltext)
{
struct elfNN_ia64_dyn_reloc_entry *rent;
rent->count = 0;
dyn_i->reloc_entries = rent;
}
+ rent->reltext = reltext;
rent->count++;
return TRUE;
if (!srel)
return FALSE;
}
- if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type))
+ if (!count_dyn_reloc (abfd, dyn_i, srel, dynrel_type,
+ (sec->flags & SEC_READONLY) != 0))
return FALSE;
}
}
default:
abort ();
}
+ if (rent->reltext)
+ ia64_info->reltext = 1;
rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count;
}
if (strip)
ia64_info->fptr_sec = NULL;
}
+ else if (sec == ia64_info->rel_fptr_sec)
+ {
+ if (strip)
+ ia64_info->rel_fptr_sec = NULL;
+ else
+ /* We use the reloc_count field as a counter if we need to
+ copy relocs into the output file. */
+ sec->reloc_count = 0;
+ }
else if (sec == ia64_info->plt_sec)
{
if (strip)
elfNN_ia64_tprel_base (info)
struct bfd_link_info *info;
{
- struct elf_link_tls_segment *tls_segment
- = elf_hash_table (info)->tls_segment;
+ asection *tls_sec = elf_hash_table (info)->tls_sec;
- BFD_ASSERT (tls_segment != NULL);
- return (tls_segment->start
- - align_power ((bfd_vma) 16, tls_segment->align));
+ BFD_ASSERT (tls_sec != NULL);
+ return tls_sec->vma - align_power ((bfd_vma) 16, tls_sec->alignment_power);
}
/* Return the base VMA address which should be subtracted from real addresses
elfNN_ia64_dtprel_base (info)
struct bfd_link_info *info;
{
- BFD_ASSERT (elf_hash_table (info)->tls_segment != NULL);
- return elf_hash_table (info)->tls_segment->start;
+ BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
+ return elf_hash_table (info)->tls_sec->vma;
}
/* Called through qsort to sort the .IA_64.unwind section during a
if (r_symndx < symtab_hdr->sh_info)
{
/* Reloc against local symbol. */
+ asection *msec;
sym = local_syms + r_symndx;
sym_sec = local_sections[r_symndx];
- value = _bfd_elf_rela_local_sym (output_bfd, sym, sym_sec, rel);
+ msec = sym_sec;
+ value = _bfd_elf_rela_local_sym (output_bfd, sym, &msec, rel);
if ((sym_sec->flags & SEC_MERGE)
&& ELF_ST_TYPE (sym->st_info) == STT_SECTION
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
if (loc_h && ! loc_h->sec_merge_done)
{
struct elfNN_ia64_dyn_sym_info *dynent;
- asection *msec;
for (dynent = loc_h->info; dynent; dynent = dynent->next)
{
BFD_ASSERT (srel != NULL);
+ switch (r_type)
+ {
+ case R_IA64_IMM14:
+ case R_IA64_IMM22:
+ case R_IA64_IMM64:
+ /* ??? People shouldn't be doing non-pic code in
+ shared libraries nor dynamic executables. */
+ (*_bfd_error_handler)
+ (_("%s: non-pic code with imm relocation against dynamic symbol `%s'"),
+ bfd_archive_filename (input_bfd),
+ h->root.root.string);
+ ret_val = FALSE;
+ continue;
+
+ default:
+ break;
+ }
+
/* If we don't need dynamic symbol lookup, find a
matching RELATIVE relocation. */
dyn_r_type = r_type;
break;
default:
- /* We can't represent this without a dynamic symbol.
- Adjust the relocation to be against an output
- section symbol, which are always present in the
- dynamic symbol table. */
- /* ??? People shouldn't be doing non-pic code in
- shared libraries. Hork. */
- (*_bfd_error_handler)
- (_("%s: linking non-pic code in a shared library"),
- bfd_archive_filename (input_bfd));
- ret_val = FALSE;
- continue;
+ break;
}
dynindx = 0;
addend = value;
/* Stuff for the BFD linker: */
#define bfd_elfNN_bfd_link_hash_table_create \
elfNN_ia64_hash_table_create
+#define bfd_elfNN_bfd_link_hash_table_free \
+ elfNN_ia64_hash_table_free
#define elf_backend_create_dynamic_sections \
elfNN_ia64_create_dynamic_sections
#define elf_backend_check_relocs \
#define elf_backend_want_plt_sym 0
#define elf_backend_plt_alignment 5
#define elf_backend_got_header_size 0
-#define elf_backend_plt_header_size PLT_HEADER_SIZE
#define elf_backend_want_got_plt 1
#define elf_backend_may_use_rel_p 1
#define elf_backend_may_use_rela_p 1