/* IA-64 support for 64-bit ELF
- Copyright 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ 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-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
PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
bfd_boolean *again));
static void elfNN_ia64_relax_ldxmov
- PARAMS((bfd *abfd, bfd_byte *contents, bfd_vma off));
+ 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_from_shdr
- PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
static bfd_boolean elfNN_ia64_section_flags
- PARAMS ((flagword *, Elf_Internal_Shdr *));
+ 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, const Elf_Internal_Sym *sym,
+ PARAMS ((bfd *abfd, struct bfd_link_info *info, Elf_Internal_Sym *sym,
const char **namep, flagword *flagsp, asection **secp,
bfd_vma *valp));
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));
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 *abfd, bfd_byte *hit_addr, bfd_vma val, unsigned int r_type));
+ 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,
IA64_HOWTO (R_IA64_TPREL14, "TPREL14", 0, FALSE, FALSE),
IA64_HOWTO (R_IA64_TPREL22, "TPREL22", 0, FALSE, FALSE),
IA64_HOWTO (R_IA64_TPREL64I, "TPREL64I", 0, FALSE, FALSE),
- IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 8, FALSE, FALSE),
- IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 8, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_TPREL64MSB, "TPREL64MSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_TPREL64LSB, "TPREL64LSB", 4, FALSE, FALSE),
IA64_HOWTO (R_IA64_LTOFF_TPREL22, "LTOFF_TPREL22", 0, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPMOD64MSB, "TPREL64MSB", 8, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPMOD64LSB, "TPREL64LSB", 8, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPMOD64MSB, "DTPMOD64MSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPMOD64LSB, "DTPMOD64LSB", 4, FALSE, FALSE),
IA64_HOWTO (R_IA64_LTOFF_DTPMOD22, "LTOFF_DTPMOD22", 0, FALSE, FALSE),
IA64_HOWTO (R_IA64_DTPREL14, "DTPREL14", 0, FALSE, FALSE),
IA64_HOWTO (R_IA64_DTPREL22, "DTPREL22", 0, FALSE, FALSE),
IA64_HOWTO (R_IA64_DTPREL64I, "DTPREL64I", 0, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 4, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 4, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 8, FALSE, FALSE),
- IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 8, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL32MSB, "DTPREL32MSB", 2, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL32LSB, "DTPREL32LSB", 2, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL64MSB, "DTPREL64MSB", 4, FALSE, FALSE),
+ IA64_HOWTO (R_IA64_DTPREL64LSB, "DTPREL64LSB", 4, FALSE, FALSE),
IA64_HOWTO (R_IA64_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, FALSE, FALSE),
};
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, 0x30, 0x28, 0xc0, /* ld8 r16=[r15],8 */
+ 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 */
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_byte *contents, bfd_vma off)
+{
+ unsigned int template, t0, t1, t2, t3;
+ bfd_byte *hit_addr;
+
+ hit_addr = (bfd_byte *) (contents + off);
+ hit_addr -= (long) hit_addr & 0x3;
+ t0 = bfd_getl32 (hit_addr + 0);
+ t1 = bfd_getl32 (hit_addr + 4);
+ t2 = bfd_getl32 (hit_addr + 8);
+ t3 = bfd_getl32 (hit_addr + 12);
+
+ /* Turn a MLX bundle into a MBB bundle with the same stop-bit
+ variety. */
+ template = 0x12;
+ if ((t0 & 0x1f) == 5)
+ template += 1;
+
+ /* Keep the instruction in slot 0. */
+ t0 &= 0xffffffe0;
+ t1 &= 0x3fff;
+
+ t0 |= template;
+
+ /* For slot 2, turn brl into br by masking out bit 40. */
+ t2 &= 0xff800000;
+ t3 &= 0x7fffffff;
+
+ /* Use nop.b for slot 1. */
+ t2 |= 0x100000;
+
+ bfd_putl32 (t0, hit_addr);
+ bfd_putl32 (t1, hit_addr + 4);
+ bfd_putl32 (t2, hit_addr + 8);
+ bfd_putl32 (t3, hit_addr + 12);
+}
\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;
- /* If this is the first time we have been called for this section,
- initialize the cooked size. */
- if (sec->_cooked_size == 0)
- sec->_cooked_size = sec->_raw_size;
-
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* Load the relocations for this section. */
contents = elf_section_data (sec)->this_hdr.contents;
else
{
- contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
- if (contents == NULL)
- goto error_return;
-
- if (! bfd_get_section_contents (abfd, sec, contents,
- (file_ptr) 0, sec->_raw_size))
+ if (!bfd_malloc_and_get_section (abfd, sec, &contents))
goto error_return;
}
bfd_size_type amt;
bfd_boolean is_branch;
struct elfNN_ia64_dyn_sym_info *dyn_i;
+ char symtype;
switch (r_type)
{
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)
toff = isym->st_value;
dyn_i = get_dyn_sym_info (ia64_info, NULL, abfd, irel, FALSE);
+ symtype = ELF_ST_TYPE (isym->st_info);
}
else
{
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;
tsec = h->root.u.def.section;
toff = h->root.u.def.value;
}
+
+ symtype = h->type;
}
if (tsec->sec_info_type == ELF_INFO_TYPE_MERGE)
- toff = _bfd_merged_section_offset (abfd, &tsec,
- elf_section_data (tsec)->sec_info,
- toff + irel->r_addend,
- (bfd_vma) 0);
+ {
+ /* At this stage in linking, no SEC_MERGE symbol has been
+ adjusted, so all references to such symbols need to be
+ passed through _bfd_merged_section_offset. (Later, in
+ relocate_section, all SEC_MERGE symbols *except* for
+ section symbols have been adjusted.)
+
+ gas may reduce relocations against symbols in SEC_MERGE
+ sections to a relocation against the section symbol when
+ the original addend was zero. When the reloc is against
+ a section symbol we should include the addend in the
+ offset passed to _bfd_merged_section_offset, since the
+ location of interest is the original symbol. On the
+ other hand, an access to "sym+addend" where "sym" is not
+ a section symbol should not include the addend; Such an
+ access is presumed to be an offset from "sym"; The
+ location of interest is just "sym". */
+ if (symtype == STT_SECTION)
+ toff += irel->r_addend;
+
+ toff = _bfd_merged_section_offset (abfd, &tsec,
+ elf_section_data (tsec)->sec_info,
+ toff);
+
+ if (symtype != STT_SECTION)
+ toff += irel->r_addend;
+ }
else
toff += irel->r_addend;
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 (contents, roff);
+
+ irel->r_info
+ = ELFNN_R_INFO (ELFNN_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;
+ /* We can't put a trampoline in a .init/.fini section. Issue
+ an error. */
+ if (strcmp (sec->output_section->name, ".init") == 0
+ || strcmp (sec->output_section->name, ".fini") == 0)
+ {
+ (*_bfd_error_handler)
+ (_("%B: Can't relax br at 0x%lx in section `%A'. Please use brl or indirect branch."),
+ sec->owner, sec, (unsigned long) roff);
+ bfd_set_error (bfd_error_bad_value);
+ goto error_return;
+ }
+
/* If the branch and target are in the same section, you've
- got one honking big section and we can't help you. You'll
- get an error message later. */
- if (tsec == sec)
+ got one honking big section and we can't help you unless
+ you are branching backwards. You'll get an error message
+ later. */
+ if (tsec == sec && toff > roff)
continue;
/* Look for an existing fixup to this address. */
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;
+ trampoff = (sec->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)
goto error_return;
- sec->_cooked_size = amt;
+ sec->size = amt;
if (tsec == ia64_info->plt_sec)
{
}
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),
- r_type) != bfd_reloc_ok)
+ /* Fix up the existing branch to hit the trampoline. */
+ if (elfNN_ia64_install_value (contents + roff, offset, r_type)
+ != bfd_reloc_ok)
goto error_return;
changed_contents = TRUE;
}
else
{
- elfNN_ia64_relax_ldxmov (abfd, contents, roff);
+ elfNN_ia64_relax_ldxmov (contents, roff);
irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE);
changed_contents = TRUE;
changed_relocs = TRUE;
enough that the data segment moves, which will change the GP.
Reset the GP so that we re-calculate next round. We need to
do this at the _beginning_ of the next round; now will not do. */
-
+
/* Clean up and go home. */
while (fixups)
{
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
- ia64_info->got_sec->_raw_size = data.ofs;
- ia64_info->got_sec->_cooked_size = data.ofs;
+ ia64_info->got_sec->size = data.ofs;
/* ??? 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 void
-elfNN_ia64_relax_ldxmov (abfd, contents, off)
- bfd *abfd;
+elfNN_ia64_relax_ldxmov (contents, off)
bfd_byte *contents;
bfd_vma off;
{
abort ();
}
- dword = bfd_get_64 (abfd, contents + off);
+ dword = bfd_getl64 (contents + off);
insn = (dword >> shift) & 0x1ffffffffffLL;
r1 = (insn >> 6) & 127;
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
- bfd_put_64 (abfd, dword, contents + off);
+ bfd_putl64 (dword, contents + off);
}
\f
/* Return TRUE if NAME is an unwind table section name. */
}
/* Handle an IA-64 specific section when reading an object file. This
- is called when elfcode.h finds a section with an unknown type. */
+ is called when bfd_section_from_shdr finds a section with an unknown
+ type. */
static bfd_boolean
-elfNN_ia64_section_from_shdr (abfd, hdr, name)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- const char *name;
+elfNN_ia64_section_from_shdr (bfd *abfd,
+ Elf_Internal_Shdr *hdr,
+ const char *name,
+ int shindex)
{
asection *newsect;
return FALSE;
}
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
newsect = hdr->bfd_section;
static bfd_boolean
elfNN_ia64_section_flags (flags, hdr)
flagword *flags;
- Elf_Internal_Shdr *hdr;
+ const Elf_Internal_Shdr *hdr;
{
if (hdr->sh_flags & SHF_IA_64_SHORT)
*flags |= SEC_SMALL_DATA;
bfd_boolean linker ATTRIBUTE_UNUSED;
{
Elf_Internal_Shdr *hdr;
- const char *sname;
- asection *text_sect, *s;
- size_t len;
+ asection *s;
for (s = abfd->sections; s; s = s->next)
{
switch (hdr->sh_type)
{
case SHT_IA_64_UNWIND:
- /* See comments in gas/config/tc-ia64.c:dot_endp on why we
- have to do this. */
- sname = bfd_get_section_name (abfd, s);
- len = sizeof (ELF_STRING_ia64_unwind) - 1;
- if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
- {
- sname += len;
-
- if (sname[0] == '\0')
- /* .IA_64.unwind -> .text */
- text_sect = bfd_get_section_by_name (abfd, ".text");
- else
- /* .IA_64.unwindFOO -> FOO */
- text_sect = bfd_get_section_by_name (abfd, sname);
- }
- else if (sname
- && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
- strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
- {
- /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
- size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
- char *once_name = bfd_malloc (len2 + strlen (sname + len) + 1);
-
- if (once_name != NULL)
- {
- memcpy (once_name, ".gnu.linkonce.t.", len2);
- strcpy (once_name + len2, sname + len);
- text_sect = bfd_get_section_by_name (abfd, once_name);
- free (once_name);
- }
- else
- /* Should only happen if we run out of memory, in
- which case we're probably toast anyway. Try to
- cope by finding the section the slow way. */
- for (text_sect = abfd->sections;
- text_sect != NULL;
- text_sect = text_sect->next)
- {
- if (strncmp (bfd_section_name (abfd, text_sect),
- ".gnu.linkonce.t.", len2) == 0
- && strcmp (bfd_section_name (abfd, text_sect) + len2,
- sname + len) == 0)
- break;
- }
- }
- else
- /* last resort: fall back on .text */
- text_sect = bfd_get_section_by_name (abfd, ".text");
-
- if (text_sect)
- {
- /* The IA-64 processor-specific ABI requires setting
- sh_link to the unwind section, whereas HP-UX requires
- sh_info to do so. For maximum compatibility, we'll
- set both for now... */
- hdr->sh_link = elf_section_data (text_sect)->this_idx;
- hdr->sh_info = elf_section_data (text_sect)->this_idx;
- }
+ /* The IA-64 processor-specific ABI requires setting sh_link
+ to the unwind section, whereas HP-UX requires sh_info to
+ do so. For maximum compatibility, we'll set both for
+ now... */
+ hdr->sh_info = hdr->sh_link;
break;
}
}
elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
bfd *abfd;
struct bfd_link_info *info;
- const Elf_Internal_Sym *sym;
+ Elf_Internal_Sym *sym;
const char **namep ATTRIBUTE_UNUSED;
flagword *flagsp ATTRIBUTE_UNUSED;
asection **secp;
}
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;
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_link_hash_entry *)
_bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret,
table, string));
+ ret->info = NULL;
return (struct bfd_hash_entry *) ret;
}
/* Copy down any references that we may have already seen to the
symbol which just became indirect. */
- dir->root.elf_link_hash_flags |=
- (ind->root.elf_link_hash_flags
- & (ELF_LINK_HASH_REF_DYNAMIC
- | ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_REF_REGULAR_NONWEAK));
+ dir->root.ref_dynamic |= ind->root.ref_dynamic;
+ dir->root.ref_regular |= ind->root.ref_regular;
+ dir->root.ref_regular_nonweak |= ind->root.ref_regular_nonweak;
+ dir->root.needs_plt |= ind->root.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;
const Elf_Internal_Rela *relend;
Elf_Internal_Shdr *symtab_hdr;
const Elf_Internal_Rela *rel;
- asection *got, *fptr, *srel;
+ asection *got, *fptr, *srel, *pltoff;
if (info->relocatable)
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
ia64_info = elfNN_ia64_hash_table (info);
- got = fptr = srel = NULL;
+ got = fptr = srel = pltoff = NULL;
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; ++rel)
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ h->ref_regular = 1;
}
/* We can only get preliminary data on whether a symbol is
this may help reduce memory usage and processing time later. */
maybe_dynamic = FALSE;
if (h && ((!info->executable
- && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
- || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+ && (!info->symbolic
+ || info->unresolved_syms_in_shared_libs == RM_IGNORE))
+ || !h->def_regular
|| h->root.type == bfd_link_hash_defweak))
maybe_dynamic = TRUE;
dynamic symbol table. */
if (!h && info->shared)
{
- if (! (_bfd_elfNN_link_record_local_dynamic_symbol
+ if (! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, (long) r_symndx)))
return FALSE;
}
{
if (!ia64_info->root.dynobj)
ia64_info->root.dynobj = abfd;
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 1;
dyn_i->want_plt = 1;
}
if (need_entry & NEED_FULL_PLT)
dyn_i->want_plt2 = 1;
if (need_entry & NEED_PLTOFF)
- dyn_i->want_pltoff = 1;
+ {
+ /* This is needed here, in case @pltoff is used in a non-shared
+ link. */
+ if (!pltoff)
+ {
+ pltoff = get_pltoff (abfd, info, ia64_info);
+ if (!pltoff)
+ return FALSE;
+ }
+
+ dyn_i->want_pltoff = 1;
+ }
if ((need_entry & NEED_DYNREL) && (sec->flags & SEC_ALLOC))
{
if (!srel)
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;
}
}
BFD_ASSERT ((h->root.type == bfd_link_hash_defined)
|| (h->root.type == bfd_link_hash_defweak));
- if (!_bfd_elfNN_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, h->root.u.def.section->owner,
global_sym_index (h)))
return FALSE;
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- /* ??? Versioned symbols seem to lose ELF_LINK_HASH_NEEDS_PLT. */
+ /* ??? Versioned symbols seem to lose NEEDS_PLT. */
if (elfNN_ia64_dynamic_symbol_p (h, x->info, 0))
{
bfd_size_type offset = x->ofs;
default:
abort ();
}
- rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count;
+ if (rent->reltext)
+ ia64_info->reltext = 1;
+ rent->srel->size += sizeof (ElfNN_External_Rela) * count;
}
/* Take care of the GOT and PLT relocations. */
|| !x->info->pie
|| dyn_i->h == NULL
|| dyn_i->h->root.type != bfd_link_hash_undefweak)
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
}
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
if (dynamic_symbol && dyn_i->want_dtpmod)
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
if (dynamic_symbol && dyn_i->want_dtprel)
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
{
if (dyn_i->h == NULL || dyn_i->h->root.type != bfd_link_hash_undefweak)
- ia64_info->rel_fptr_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_fptr_sec->size += sizeof (ElfNN_External_Rela);
}
if (!resolved_zero && dyn_i->want_pltoff)
else if (shared)
t = 2 * sizeof (ElfNN_External_Rela);
- ia64_info->rel_pltoff_sec->_raw_size += t;
+ ia64_info->rel_pltoff_sec->size += t;
}
return TRUE;
/* 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->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
+ 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;
return TRUE;
}
sec = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (sec != NULL);
sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
- sec->_raw_size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
+ sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
}
/* Allocate the GOT entries. */
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
- ia64_info->got_sec->_raw_size = data.ofs;
+ ia64_info->got_sec->size = data.ofs;
}
/* Allocate the FPTR entries. */
{
data.ofs = 0;
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_fptr, &data);
- ia64_info->fptr_sec->_raw_size = data.ofs;
+ ia64_info->fptr_sec->size = data.ofs;
}
/* Now that we've seen all of the input files, we can decide which
data.ofs = (data.ofs + 31) & (bfd_vma) -32;
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_plt2_entries, &data);
- if (data.ofs != 0)
+ if (data.ofs != 0 || ia64_info->root.dynamic_sections_created)
{
+ /* FIXME: we always reserve the memory for dynamic linker even if
+ there are no PLT entries since dynamic linker may assume the
+ reserved memory always exists. */
+
BFD_ASSERT (ia64_info->root.dynamic_sections_created);
- ia64_info->plt_sec->_raw_size = data.ofs;
+ ia64_info->plt_sec->size = data.ofs;
/* If we've got a .plt, we need some extra memory for the dynamic
linker. We stuff these in .got.plt. */
sec = bfd_get_section_by_name (dynobj, ".got.plt");
- sec->_raw_size = 8 * PLT_RESERVED_WORDS;
+ sec->size = 8 * PLT_RESERVED_WORDS;
}
/* Allocate the PLTOFF entries. */
{
data.ofs = 0;
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_pltoff_entries, &data);
- ia64_info->pltoff_sec->_raw_size = data.ofs;
+ ia64_info->pltoff_sec->size = data.ofs;
}
if (ia64_info->root.dynamic_sections_created)
required. */
if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
- ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
+ ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
}
function which decides whether anything needs to go into
these sections. */
- strip = (sec->_raw_size == 0);
+ strip = (sec->size == 0);
if (sec == ia64_info->got_sec)
strip = FALSE;
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)
else
{
/* Allocate memory for the section contents. */
- sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->_raw_size);
- if (sec->contents == NULL && sec->_raw_size != 0)
+ sec->contents = (bfd_byte *) bfd_zalloc (dynobj, sec->size);
+ if (sec->contents == NULL && sec->size != 0)
return FALSE;
}
}
/* The DT_DEBUG entry is filled in by the dynamic linker and used
by the debugger. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elfNN_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (!add_dynamic_entry (DT_DEBUG, 0))
return FALSE;
}
static bfd_reloc_status_type
-elfNN_ia64_install_value (abfd, hit_addr, v, r_type)
- bfd *abfd;
+elfNN_ia64_install_value (hit_addr, v, r_type)
bfd_byte *hit_addr;
bfd_vma v;
unsigned int r_type;
{
const struct ia64_operand *op;
int bigendian = 0, shift = 0;
- bfd_vma t0, t1, insn, dword;
+ bfd_vma t0, t1, dword;
+ ia64_insn insn;
enum ia64_opnd opnd;
const char *err;
size_t size = 8;
{
case IA64_OPND_IMMU64:
hit_addr -= (long) hit_addr & 0x3;
- t0 = bfd_get_64 (abfd, hit_addr);
- t1 = bfd_get_64 (abfd, hit_addr + 8);
+ t0 = bfd_getl64 (hit_addr);
+ t1 = bfd_getl64 (hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
| (((val >> 21) & 0x001) << 21) /* ic */
| (((val >> 63) & 0x001) << 36)) << 23; /* i */
- bfd_put_64 (abfd, t0, hit_addr);
- bfd_put_64 (abfd, t1, hit_addr + 8);
+ bfd_putl64 (t0, hit_addr);
+ bfd_putl64 (t1, hit_addr + 8);
break;
case IA64_OPND_TGT64:
hit_addr -= (long) hit_addr & 0x3;
- t0 = bfd_get_64 (abfd, hit_addr);
- t1 = bfd_get_64 (abfd, hit_addr + 8);
+ t0 = bfd_getl64 (hit_addr);
+ t1 = bfd_getl64 (hit_addr + 8);
/* tmpl/s: bits 0.. 5 in t0
slot 0: bits 5..45 in t0
t1 |= ((((val >> 0) & 0xfffffLL) << 13) /* imm20b */
| (((val >> 59) & 0x1LL) << 36)) << 23; /* i */
- bfd_put_64 (abfd, t0, hit_addr);
- bfd_put_64 (abfd, t1, hit_addr + 8);
+ bfd_putl64 (t0, hit_addr);
+ bfd_putl64 (t1, hit_addr + 8);
break;
default:
case 2: shift = 23; hit_addr += 6; break;
case 3: return bfd_reloc_notsupported; /* shouldn't happen... */
}
- dword = bfd_get_64 (abfd, hit_addr);
+ dword = bfd_getl64 (hit_addr);
insn = (dword >> shift) & 0x1ffffffffffLL;
op = elf64_ia64_operands + opnd;
- err = (*op->insert) (op, val, (ia64_insn *)& insn);
+ err = (*op->insert) (op, val, &insn);
if (err)
return bfd_reloc_overflow;
dword &= ~(0x1ffffffffffLL << shift);
dword |= (insn << shift);
- bfd_put_64 (abfd, dword, hit_addr);
+ bfd_putl64 (dword, hit_addr);
break;
case IA64_OPND_NIL:
loc = srel->contents;
loc += srel->reloc_count++ * sizeof (ElfNN_External_Rela);
bfd_elfNN_swap_reloca_out (abfd, &outrel, loc);
- BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count
- <= srel->_cooked_size);
+ BFD_ASSERT (sizeof (ElfNN_External_Rela) * srel->reloc_count <= srel->size);
}
/* Store an entry for target address TARGET_ADDR in the linkage table
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
continue;
lo = os->vma;
- hi = os->vma + os->_raw_size;
+ hi = os->vma + os->size;
if (hi < lo)
hi = (bfd_vma) -1;
{
unwind_output_sec = s->output_section;
unwind_output_sec->contents
- = bfd_malloc (unwind_output_sec->_raw_size);
+ = bfd_malloc (unwind_output_sec->size);
if (unwind_output_sec->contents == NULL)
return FALSE;
}
}
/* Invoke the regular ELF backend linker to do all the work. */
- if (!bfd_elfNN_bfd_final_link (abfd, info))
+ if (!bfd_elf_final_link (abfd, info))
return FALSE;
if (unwind_output_sec)
{
elfNN_ia64_unwind_entry_compare_bfd = abfd;
qsort (unwind_output_sec->contents,
- (size_t) (unwind_output_sec->_raw_size / 24),
+ (size_t) (unwind_output_sec->size / 24),
24,
elfNN_ia64_unwind_entry_compare);
if (! bfd_set_section_contents (abfd, unwind_output_sec,
unwind_output_sec->contents, (bfd_vma) 0,
- unwind_output_sec->_raw_size))
+ unwind_output_sec->size))
return FALSE;
}
if (r_type > R_IA64_MAX_RELOC_CODE)
{
(*_bfd_error_handler)
- (_("%s: unknown relocation type %d"),
- bfd_archive_filename (input_bfd), (int)r_type);
+ (_("%B: unknown relocation type %d"),
+ input_bfd, (int) r_type);
bfd_set_error (bfd_error_bad_value);
ret_val = FALSE;
continue;
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)
{
elf_section_data (msec)->
sec_info,
sym->st_value
- + dynent->addend,
- (bfd_vma) 0);
+ + dynent->addend);
dynent->addend -= sym->st_value;
dynent->addend += msec->output_section->vma
+ msec->output_offset
{
bfd_boolean unresolved_reloc;
bfd_boolean warned;
+ struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd);
- RELOC_FOR_GLOBAL_SYMBOL (h, elf_sym_hashes (input_bfd),
- r_symndx,
- symtab_hdr, value, sym_sec,
- unresolved_reloc, info,
- warned);
+ RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
+ r_symndx, symtab_hdr, sym_hashes,
+ h, sym_sec, value,
+ unresolved_reloc, warned);
if (h->root.type == bfd_link_hash_undefweak)
undef_weak_ref = TRUE;
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)
+ (_("%B: 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,
+ sym_sec));
+ 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;
case R_IA64_LTV32LSB:
case R_IA64_LTV64MSB:
case R_IA64_LTV64LSB:
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_GPREL22:
if (dynamic_symbol_p)
{
(*_bfd_error_handler)
- (_("%s: @gprel relocation against dynamic symbol %s"),
- bfd_archive_filename (input_bfd), h->root.root.string);
+ (_("%B: @gprel relocation against dynamic symbol %s"),
+ input_bfd,
+ h ? h->root.root.string
+ : bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+ sym_sec));
ret_val = FALSE;
continue;
}
value -= gp_val;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF22:
value = set_got_entry (input_bfd, info, dyn_i, (h ? h->dynindx : -1),
rel->r_addend, value, R_IA64_DIR64LSB);
value -= gp_val;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_PLTOFF22:
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 = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_FPTR64I:
/* ??? People shouldn't be doing non-pic code in
shared libraries. Hork. */
(*_bfd_error_handler)
- (_("%s: linking non-pic code in a position independent executable"),
- bfd_archive_filename (input_bfd));
+ (_("%B: linking non-pic code in a position independent executable"),
+ input_bfd);
ret_val = FALSE;
continue;
}
dynindx, addend);
}
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF_FPTR22:
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
if (dyn_i->want_fptr)
{
- BFD_ASSERT (h == NULL || h->dynindx == -1)
+ BFD_ASSERT (h == NULL || h->dynindx == -1);
if (!undef_weak_ref)
value = set_fptr_entry (output_bfd, info, dyn_i, value);
dynindx = -1;
value = set_got_entry (output_bfd, info, dyn_i, dynindx,
rel->r_addend, value, R_IA64_FPTR64LSB);
value -= gp_val;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
case R_IA64_PCREL64I:
/* The PCREL21BI reloc is specifically not intended for use with
dynamic relocs. PCREL21F and PCREL21M are used for speculation
- fixup code, and thus probably ought not be dynamic. The
+ fixup code, and thus probably ought not be dynamic. The
PCREL22 and PCREL64I relocs aren't emitted as dynamic relocs. */
if (dynamic_symbol_p)
{
const char *msg;
if (r_type == R_IA64_PCREL21BI)
- msg = _("%s: @internal branch to dynamic symbol %s");
+ msg = _("%B: @internal branch to dynamic symbol %s");
else if (r_type == R_IA64_PCREL21F || r_type == R_IA64_PCREL21M)
- msg = _("%s: speculation fixup to dynamic symbol %s");
+ msg = _("%B: speculation fixup to dynamic symbol %s");
else
- msg = _("%s: @pcrel relocation against dynamic symbol %s");
- (*_bfd_error_handler) (msg, bfd_archive_filename (input_bfd),
- h->root.root.string);
+ msg = _("%B: @pcrel relocation against dynamic symbol %s");
+ (*_bfd_error_handler) (msg, input_bfd,
+ h ? h->root.root.string
+ : bfd_elf_sym_name (input_bfd,
+ symtab_hdr,
+ sym,
+ sym_sec));
ret_val = FALSE;
continue;
}
value -= (input_section->output_section->vma
+ input_section->output_offset
+ rel->r_offset) & ~ (bfd_vma) 0x3;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_SEGREL32MSB:
value -= p->p_vaddr;
else
value = 0;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
- r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
}
case R_IA64_SECREL32LSB:
case R_IA64_SECREL64MSB:
case R_IA64_SECREL64LSB:
- /* Make output-section relative. */
- if (value > input_section->output_section->vma)
- value -= input_section->output_section->vma;
- else
- value = 0;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ /* Make output-section relative to section where the symbol
+ is defined. PR 475 */
+ if (sym_sec)
+ value -= sym_sec->output_section->vma;
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_IPLTMSB:
r_type = R_IA64_DIR64MSB;
else
r_type = R_IA64_DIR64LSB;
- elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
- r = elfNN_ia64_install_value (output_bfd, hit_addr + 8, gp_val,
- r_type);
+ elfNN_ia64_install_value (hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr + 8, gp_val, r_type);
break;
case R_IA64_TPREL14:
case R_IA64_TPREL22:
case R_IA64_TPREL64I:
value -= elfNN_ia64_tprel_base (info);
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_DTPREL14:
case R_IA64_DTPREL64LSB:
case R_IA64_DTPREL64MSB:
value -= elfNN_ia64_dtprel_base (info);
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
break;
case R_IA64_LTOFF_TPREL22:
value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
value, got_r_type);
value -= gp_val;
- r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
- r_type);
+ r = elfNN_ia64_install_value (hit_addr, value, r_type);
}
break;
if (h)
name = h->root.root.string;
else
- {
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (name == NULL)
- return FALSE;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, input_section);
- }
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+ sym_sec);
if (!(*info->callbacks->warning) (info, _("unsupported reloc"),
name, input_bfd,
input_section, rel->r_offset))
if (h)
name = h->root.root.string;
else
+ name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
+ sym_sec);
+
+ switch (r_type)
{
- name = bfd_elf_string_from_elf_section (input_bfd,
- symtab_hdr->sh_link,
- sym->st_name);
- if (name == NULL)
+ case R_IA64_PCREL21B:
+ case R_IA64_PCREL21BI:
+ case R_IA64_PCREL21M:
+ case R_IA64_PCREL21F:
+ if (is_elf_hash_table (info->hash))
+ {
+ /* Relaxtion is always performed for ELF output.
+ Overflow failures for those relocations mean
+ that the section is too big to relax. */
+ (*_bfd_error_handler)
+ (_("%B: Can't relax br (%s) to `%s' at 0x%lx in section `%A' with size 0x%lx (> 0x1000000)."),
+ input_bfd, input_section, howto->name, name,
+ rel->r_offset, input_section->size);
+ break;
+ }
+ default:
+ if (!(*info->callbacks->reloc_overflow) (info,
+ &h->root,
+ name,
+ howto->name,
+ (bfd_vma) 0,
+ input_bfd,
+ input_section,
+ rel->r_offset))
return FALSE;
- if (*name == '\0')
- name = bfd_section_name (input_bfd, input_section);
+ break;
}
- if (!(*info->callbacks->reloc_overflow) (info, name,
- howto->name,
- (bfd_vma) 0,
- input_bfd,
- input_section,
- rel->r_offset))
- return FALSE;
+
ret_val = FALSE;
}
break;
loc = plt_sec->contents + dyn_i->plt_offset;
memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
- elfNN_ia64_install_value (output_bfd, loc, index, R_IA64_IMM22);
- elfNN_ia64_install_value (output_bfd, loc+2, -dyn_i->plt_offset,
- R_IA64_PCREL21B);
+ elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
+ elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
plt_addr = (plt_sec->output_section->vma
+ plt_sec->output_offset
loc = plt_sec->contents + dyn_i->plt2_offset;
memcpy (loc, plt_full_entry, PLT_FULL_ENTRY_SIZE);
- elfNN_ia64_install_value (output_bfd, loc, pltoff_addr - gp_val,
- R_IA64_IMM22);
+ elfNN_ia64_install_value (loc, pltoff_addr - gp_val, R_IA64_IMM22);
/* Mark the symbol as undefined, rather than as defined in the
plt section. Leave the value alone. */
/* ??? We didn't redefine it in adjust_dynamic_symbol in the
- first place. But perhaps elflink.h did some for us. */
- if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
+ first place. But perhaps elflink.c did some for us. */
+ if (!h->def_regular)
sym->st_shndx = SHN_UNDEF;
}
sgotplt = bfd_get_section_by_name (dynobj, ".got.plt");
BFD_ASSERT (sdyn != NULL);
dyncon = (ElfNN_External_Dyn *) sdyn->contents;
- dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size);
gp_val = _bfd_get_gp_value (abfd);
+ sgotplt->output_offset
- gp_val);
- elfNN_ia64_install_value (abfd, loc+1, pltres, R_IA64_GPREL22);
+ elfNN_ia64_install_value (loc+1, pltres, R_IA64_GPREL22);
}
}
if ((in_flags & EF_IA_64_TRAPNIL) != (out_flags & EF_IA_64_TRAPNIL))
{
(*_bfd_error_handler)
- (_("%s: linking trap-on-NULL-dereference with non-trapping files"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking trap-on-NULL-dereference with non-trapping files"),
+ ibfd);
bfd_set_error (bfd_error_bad_value);
ok = FALSE;
if ((in_flags & EF_IA_64_BE) != (out_flags & EF_IA_64_BE))
{
(*_bfd_error_handler)
- (_("%s: linking big-endian files with little-endian files"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking big-endian files with little-endian files"),
+ ibfd);
bfd_set_error (bfd_error_bad_value);
ok = FALSE;
if ((in_flags & EF_IA_64_ABI64) != (out_flags & EF_IA_64_ABI64))
{
(*_bfd_error_handler)
- (_("%s: linking 64-bit files with 32-bit files"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking 64-bit files with 32-bit files"),
+ ibfd);
bfd_set_error (bfd_error_bad_value);
ok = FALSE;
if ((in_flags & EF_IA_64_CONS_GP) != (out_flags & EF_IA_64_CONS_GP))
{
(*_bfd_error_handler)
- (_("%s: linking constant-gp files with non-constant-gp files"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking constant-gp files with non-constant-gp files"),
+ ibfd);
bfd_set_error (bfd_error_bad_value);
ok = FALSE;
!= (out_flags & EF_IA_64_NOFUNCDESC_CONS_GP))
{
(*_bfd_error_handler)
- (_("%s: linking auto-pic files with non-auto-pic files"),
- bfd_archive_filename (ibfd));
+ (_("%B: linking auto-pic files with non-auto-pic files"),
+ ibfd);
bfd_set_error (bfd_error_bad_value);
ok = FALSE;
static struct bfd_elf_special_section const elfNN_ia64_special_sections[]=
{
- { ".sbss", 0, NULL, 0,
- SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
- { ".sdata", 0, NULL, 0,
- SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_IA_64_SHORT },
- { NULL, 0, NULL, 0,
- 0, 0 }
+ { ".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 }
};
+static bfd_boolean
+elfNN_ia64_object_p (bfd *abfd)
+{
+ asection *sec;
+ asection *group, *unwi, *unw;
+ flagword flags;
+ const char *name;
+ char *unwi_name, *unw_name;
+ bfd_size_type amt;
+
+ if (abfd->flags & DYNAMIC)
+ return TRUE;
+
+ /* Flags for fake group section. */
+ flags = (SEC_LINKER_CREATED | SEC_GROUP | SEC_LINK_ONCE
+ | SEC_EXCLUDE);
+
+ /* We add a fake section group for each .gnu.linkonce.t.* section,
+ which isn't in a section group, and its unwind sections. */
+ for (sec = abfd->sections; sec != NULL; sec = sec->next)
+ {
+ 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)
+ {
+ name = sec->name + 16;
+
+ amt = strlen (name) + sizeof (".gnu.linkonce.ia64unwi.");
+ unwi_name = bfd_alloc (abfd, amt);
+ if (!unwi_name)
+ return FALSE;
+
+ strcpy (stpcpy (unwi_name, ".gnu.linkonce.ia64unwi."), name);
+ unwi = bfd_get_section_by_name (abfd, unwi_name);
+
+ amt = strlen (name) + sizeof (".gnu.linkonce.ia64unw.");
+ unw_name = bfd_alloc (abfd, amt);
+ if (!unw_name)
+ return FALSE;
+
+ strcpy (stpcpy (unw_name, ".gnu.linkonce.ia64unw."), name);
+ unw = bfd_get_section_by_name (abfd, unw_name);
+
+ /* We need to create a fake group section for it and its
+ unwind sections. */
+ group = bfd_make_section_anyway (abfd, name);
+ if (group == NULL
+ || ! bfd_set_section_flags (abfd, group, flags))
+ return FALSE;
+
+ /* Move the fake group section to the beginning. */
+ bfd_section_list_remove (abfd, group);
+ bfd_section_list_insert_before (abfd, abfd->sections, group);
+
+ elf_next_in_group (group) = sec;
+
+ elf_group_name (sec) = name;
+ elf_next_in_group (sec) = sec;
+ elf_sec_group (sec) = group;
+
+ if (unwi)
+ {
+ elf_group_name (unwi) = name;
+ elf_next_in_group (unwi) = sec;
+ elf_next_in_group (sec) = unwi;
+ elf_sec_group (unwi) = group;
+ }
+
+ if (unw)
+ {
+ elf_group_name (unw) = name;
+ if (unwi)
+ {
+ elf_next_in_group (unw) = elf_next_in_group (unwi);
+ elf_next_in_group (unwi) = unw;
+ }
+ else
+ {
+ elf_next_in_group (unw) = sec;
+ elf_next_in_group (sec) = unw;
+ }
+ elf_sec_group (unw) = group;
+ }
+
+ /* Fake SHT_GROUP section header. */
+ elf_section_data (group)->this_hdr.bfd_section = group;
+ elf_section_data (group)->this_hdr.sh_type = SHT_GROUP;
+ }
+ }
+ return TRUE;
+}
+
static bfd_boolean
elfNN_ia64_hpux_vec (const bfd_target *vec)
{
}
return FALSE;
}
+
+static void
+elfNN_hpux_backend_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
+ asymbol *asym)
+{
+ elf_symbol_type *elfsym = (elf_symbol_type *) asym;;
+
+ switch (elfsym->internal_elf_sym.st_shndx)
+ {
+ case SHN_IA_64_ANSI_COMMON:
+ asym->section = bfd_com_section_ptr;
+ asym->value = elfsym->internal_elf_sym.st_size;
+ asym->flags &= ~BSF_GLOBAL;
+ break;
+ }
+}
+
\f
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
#define TARGET_LITTLE_NAME "elfNN-ia64-little"
#define bfd_elfNN_bfd_relax_section \
elfNN_ia64_relax_section
+#define elf_backend_object_p \
+ elfNN_ia64_object_p
+
/* 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
#define elf_backend_rela_normal 1
#define elf_backend_special_sections elfNN_ia64_special_sections
+/* FIXME: PR 290: The Intel C compiler generates SHT_IA_64_UNWIND with
+ SHF_LINK_ORDER. But it doesn't set theh sh_link or sh_info fields.
+ We don't want to flood users with so many error messages. We turn
+ off the warning for now. It will be turned on later when the Intel
+ compiler is fixed. */
+#define elf_backend_link_order_error_handler NULL
+
#include "elfNN-target.h"
/* HPUX-specific vectors. */
#undef elf_backend_section_from_bfd_section
#define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
+#undef elf_backend_symbol_processing
+#define elf_backend_symbol_processing elfNN_hpux_backend_symbol_processing
+
#undef elf_backend_want_p_paddr_set_to_zero
#define elf_backend_want_p_paddr_set_to_zero 1