reloc->address += input_section->output_offset;
return bfd_reloc_ok;
}
+
+ if (input_section->flags & SEC_DEBUGGING)
+ return bfd_reloc_continue;
+
*error_message = "Unsupported call to elfNN_ia64_reloc";
return bfd_reloc_notsupported;
}
#define DYNAMIC_INTERPRETER(abfd) \
(elfNN_ia64_aix_vec (abfd->xvec) ? AIX_DYNAMIC_INTERPRETER : ELF_DYNAMIC_INTERPRETER)
-/* Select out of range branch fixup type. Note that Itanium does
- not support brl, and so it gets emulated by the kernel. */
-#undef USE_BRL
-
-#ifdef USE_BRL
static const bfd_byte oor_brl[16] =
{
0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */
0x00, 0x00, 0x00, 0xc0
};
-#else
-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;; */
-};
-#endif
\f
/* These functions do relaxation for IA-64 ELF. */
one pass. */
*again = FALSE;
- /* Nothing to do if there are no relocations. */
+ /* Don't even try to relax for non-ELF outputs. */
+ if (link_info->hash->creator->flavour != bfd_target_elf_flavour)
+ 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)
+ || sec->reloc_count == 0
+ || (link_info->relax_finalizing
+ && sec->need_finalize_relax == 0))
return TRUE;
/* If this is the first time we have been called for this section,
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* Load the relocations for this section. */
- internal_relocs = (_bfd_elfNN_link_read_relocs
+ internal_relocs = (_bfd_elf_link_read_relocs
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
link_info->keep_memory));
if (internal_relocs == NULL)
case R_IA64_PCREL21BI:
case R_IA64_PCREL21M:
case R_IA64_PCREL21F:
+ if (link_info->relax_finalizing)
+ continue;
is_branch = TRUE;
break;
case R_IA64_LTOFF22X:
case R_IA64_LDXMOV:
+ if (!link_info->relax_finalizing)
+ {
+ sec->need_finalize_relax = 1;
+ continue;
+ }
is_branch = FALSE;
break;
goto error_return;
}
- isym = isymbuf + ELF64_R_SYM (irel->r_info);
+ isym = isymbuf + ELFNN_R_SYM (irel->r_info);
if (isym->st_shndx == SHN_UNDEF)
continue; /* We can't do anthing with undefined symbols. */
else if (isym->st_shndx == SHN_ABS)
tsec = ia64_info->plt_sec;
toff = dyn_i->plt2_offset;
+ BFD_ASSERT (irel->r_addend == 0);
}
/* Can't do anything else with dynamic symbols. */
}
}
- symaddr = (tsec->output_section->vma
- + tsec->output_offset
- + toff
- + irel->r_addend);
+ 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);
+ else
+ toff += irel->r_addend;
+
+ symaddr = tsec->output_section->vma + tsec->output_offset + toff;
roff = irel->r_offset;
size = sizeof (plt_full_entry);
else
{
-#ifdef USE_BRL
size = sizeof (oor_brl);
-#else
- size = sizeof (oor_ip);
-#endif
}
/* Resize the current section to make room for the new branch. */
}
else
{
-#ifdef USE_BRL
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;
-#else
- 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;
-#endif
}
/* Record the fixup so we don't do it again this section. */
}
/* If the data is out of range, do nothing. */
- if ((bfd_signed_vma) (symaddr - gp) >= 0x400000
- ||(bfd_signed_vma) (symaddr - gp) < -0x400000)
+ if ((bfd_signed_vma) (symaddr - gp) >= 0x200000
+ ||(bfd_signed_vma) (symaddr - gp) < -0x200000)
continue;
if (r_type == R_IA64_LTOFF22X)
struct elfNN_ia64_allocate_data data;
data.info = link_info;
data.ofs = 0;
+ ia64_info->self_dtpmod_offset = (bfd_vma) -1;
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
/* ??? Resize .rela.got too. */
}
+ if (link_info->relax_finalizing)
+ sec->need_finalize_relax = 0;
+
*again = changed_contents || changed_relocs;
return TRUE;
case 0: shift = 5; break;
case 1: shift = 14; off += 3; break;
case 2: shift = 23; off += 6; break;
- case 3:
+ default:
abort ();
}
bfd_vma *valp;
{
if (sym->st_shndx == SHN_COMMON
- && !info->relocateable
+ && !info->relocatable
&& sym->st_size <= elf_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are
if (! elf_hash_table (info)->dynamic_sections_created
&& abfd->xvec == info->hash->creator)
{
- if (! bfd_elfNN_link_create_dynamic_sections (abfd, info))
+ if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
return FALSE;
}
_bfd_elf_link_hash_hide_symbol (info, &h->root, force_local);
for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
- dyn_i->want_plt2 = 0;
+ {
+ dyn_i->want_plt2 = 0;
+ dyn_i->want_plt = 0;
+ }
}
/* Create the derived linker hash table. The IA-64 ELF port uses this
{
struct elfNN_ia64_link_hash_table *ret;
- ret = bfd_zalloc (abfd, (bfd_size_type) sizeof (*ret));
+ ret = bfd_zmalloc ((bfd_size_type) sizeof (*ret));
if (!ret)
return 0;
+
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
elfNN_ia64_new_elf_hash_entry))
{
- bfd_release (abfd, ret);
+ free (ret);
return 0;
}
if (!elfNN_ia64_local_hash_table_init (&ret->loc_hash_table, abfd,
elfNN_ia64_new_loc_hash_entry))
- return 0;
+ {
+ free (ret);
+ return 0;
+ }
+
return &ret->root.root;
}
struct elfNN_ia64_local_hash_entry *loc_h;
loc_h = get_local_sym_hash (ia64_info, abfd, rel, create);
- BFD_ASSERT (loc_h);
+ if (!loc_h)
+ {
+ BFD_ASSERT (!create);
+ return NULL;
+ }
pp = &loc_h->info;
}
const Elf_Internal_Rela *rel;
asection *got, *fptr, *srel;
- if (info->relocateable)
+ if (info->relocatable)
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- if (x->info->shared
+ if ((x->info->shared
+ && (!h
+ || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
+ || h->root.type != bfd_link_hash_undefweak))
/* AIX needs an FPTR in this case. */
|| (elfNN_ia64_aix_vec (x->info->hash->creator)
&& (!h
struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
struct elfNN_ia64_link_hash_table *ia64_info;
struct elfNN_ia64_dyn_reloc_entry *rent;
- bfd_boolean dynamic_symbol, shared;
+ bfd_boolean dynamic_symbol, shared, resolved_zero;
ia64_info = elfNN_ia64_hash_table (x->info);
dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
|| (elfNN_ia64_aix_vec (x->info->hash->creator)
/* Don't allocate an entry for __GLOB_DATA_PTR */
&& (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
- "__GLOB_DATA_PTR") != 0));
+ "__GLOB_DATA_PTR") != 0));
shared = x->info->shared;
+ resolved_zero = (dyn_i->h
+ && ELF_ST_VISIBILITY (dyn_i->h->other)
+ && dyn_i->h->root.type == bfd_link_hash_undefweak);
/* Take care of the normal data relocations. */
/* Take care of the GOT and PLT relocations. */
- if (((dynamic_symbol || shared) && (dyn_i->want_got || dyn_i->want_gotx))
- || (dyn_i->want_ltoff_fptr && dyn_i->h && dyn_i->h->dynindx != -1))
+ if ((!resolved_zero
+ && (dynamic_symbol || shared)
+ && (dyn_i->want_got || dyn_i->want_gotx))
+ || (dyn_i->want_ltoff_fptr
+ && dyn_i->h
+ && dyn_i->h->dynindx != -1))
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
if (dynamic_symbol && dyn_i->want_dtprel)
ia64_info->rel_got_sec->_raw_size += sizeof (ElfNN_External_Rela);
- if (dyn_i->want_pltoff)
+ if (!resolved_zero && dyn_i->want_pltoff)
{
bfd_size_type t = 0;
/* Set the contents of the .interp section to the interpreter. */
if (ia64_info->root.dynamic_sections_created
- && !info->shared)
+ && info->executable)
{
sec = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (sec != NULL);
later (in finish_dynamic_sections) but we must add the entries now
so that we get the correct size for the .dynamic section. */
- if (!info->shared)
+ if (info->executable)
{
/* The DT_DEBUG entry is filled in by the dynamic linker and used
by the debugger. */
bfd_put_64 (abfd, value, got_sec->contents + got_offset);
/* Install a dynamic relocation if needed. */
- if ((info->shared && dyn_r_type != R_IA64_DTPREL64LSB)
+ if ((info->shared
+ && (!dyn_i->h
+ || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ || dyn_i->h->root.type != bfd_link_hash_undefweak)
+ && dyn_r_type != R_IA64_DTPREL64LSB)
|| elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
|| elfNN_ia64_aix_vec (abfd->xvec)
|| (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
/* Install dynamic relocations if needed. */
- if (!is_plt && info->shared)
+ if (!is_plt
+ && info->shared
+ && (!dyn_i->h
+ || ELF_ST_VISIBILITY (dyn_i->h->other) == STV_DEFAULT
+ || dyn_i->h->root.type != bfd_link_hash_undefweak))
{
unsigned int dyn_r_type;
ia64_info = elfNN_ia64_hash_table (info);
/* Make sure we've got ourselves a nice fat __gp value. */
- if (!info->relocateable)
+ if (!info->relocatable)
{
bfd_vma gp_val = _bfd_get_gp_value (abfd);
struct elf_link_hash_entry *gp;
of the .IA_64.unwind section. Force this section to be relocated
into memory rather than written immediately to the output file. */
unwind_output_sec = NULL;
- if (!info->relocateable)
+ if (!info->relocatable)
{
asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
if (s)
ia64_info = elfNN_ia64_hash_table (info);
/* Infect various flags from the input section to the output section. */
- if (info->relocateable)
+ if (info->relocatable)
{
bfd_vma flags;
asection *sym_sec;
bfd_byte *hit_addr;
bfd_boolean dynamic_symbol_p;
+ bfd_boolean local_symbol_p;
bfd_boolean undef_weak_ref;
r_type = ELFNN_R_TYPE (rel->r_info);
(!info->shared || info->no_undefined
|| ELF_ST_VISIBILITY (h->other)))))
return FALSE;
- ret_val = FALSE;
continue;
}
}
hit_addr = contents + rel->r_offset;
value += rel->r_addend;
dynamic_symbol_p = elfNN_ia64_dynamic_symbol_p (h, info);
+ /* Is this symbol locally defined? A protected symbol is locallly
+ defined. But its function descriptor may not. Use it with
+ caution. */
+ local_symbol_p = (! dynamic_symbol_p
+ || ELF_ST_VISIBILITY (h->other) != STV_DEFAULT);
switch (r_type)
{
/* If we don't need dynamic symbol lookup, find a
matching RELATIVE relocation. */
dyn_r_type = r_type;
- if (dynamic_symbol_p)
+ if (! local_symbol_p)
{
dynindx = h->dynindx;
addend = rel->r_addend;
{
int i;
for (i = m->count - 1; i >= 0; i--)
- if (m->sections[i] == sym_sec->output_section)
+ if (m->sections[i] == input_section->output_section)
break;
if (i >= 0)
break;
/* If we don't need dynamic symbol lookup, install two
RELATIVE relocations. */
- if (! dynamic_symbol_p)
+ if (local_symbol_p)
{
unsigned int dyn_r_type;