/* 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
+ Free Software Foundation, Inc.
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
This file is part of BFD, the Binary File Descriptor library.
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. */
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
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,
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 */
oor_branch_size = itanium ? sizeof (oor_ip) : sizeof (oor_brl);
}
+static void
+elfNN_ia64_relax_brl (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_getl64 (hit_addr);
+ t1 = bfd_getl64 (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_putl64 (t0, hit_addr);
+ bfd_putl64 (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;
- /* 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
+ = 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;
+ /* 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)
+ (_("%s: Can't relax br at 0x%lx in section `%s'. Please use brl or indirect branch."),
+ bfd_archive_filename (sec->owner),
+ (unsigned long) roff, sec->name);
+ 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. */
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
{
+ /* 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;
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. */
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;
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;
(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;
}
/* 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)
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 (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;
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;
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;
{
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;
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
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;
}
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)
+ (_("%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;
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:
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:
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:
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;
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;
}
value -= input_section->output_section->vma;
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_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;
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. */
+ first place. But perhaps elflink.c did some for us. */
if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0)
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);
}
}