static bfd_reloc_status_type
elfNN_ia64_reloc (abfd, reloc, sym, data, input_section,
output_bfd, error_message)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
arelent *reloc;
- asymbol *sym;
- PTR data;
+ asymbol *sym ATTRIBUTE_UNUSED;
+ PTR data ATTRIBUTE_UNUSED;
asection *input_section;
bfd *output_bfd;
char **error_message;
IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, false, true),
IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, false, true),
- IA64_HOWTO (R_IA64_SEGBASE, "SEGBASE", 4, false, true),
IA64_HOWTO (R_IA64_SEGREL32MSB, "SEGREL32MSB", 2, false, true),
IA64_HOWTO (R_IA64_SEGREL32LSB, "SEGREL32LSB", 2, false, true),
IA64_HOWTO (R_IA64_SEGREL64MSB, "SEGREL64MSB", 4, false, true),
IA64_HOWTO (R_IA64_IPLTMSB, "IPLTMSB", 4, false, true),
IA64_HOWTO (R_IA64_IPLTLSB, "IPLTLSB", 4, false, true),
- IA64_HOWTO (R_IA64_EPLTMSB, "EPLTMSB", 4, false, true),
- IA64_HOWTO (R_IA64_EPLTLSB, "EPLTLSB", 4, false, true),
IA64_HOWTO (R_IA64_COPY, "COPY", 4, false, true),
IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, false, true),
IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, false, true),
static reloc_howto_type*
elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
bfd_reloc_code_real_type bfd_code;
{
unsigned int rtype;
case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
- case BFD_RELOC_IA64_SEGBASE: rtype = R_IA64_SEGBASE; break;
case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break;
case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break;
case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break;
case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break;
case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break;
- case BFD_RELOC_IA64_EPLTMSB: rtype = R_IA64_EPLTMSB; break;
- case BFD_RELOC_IA64_EPLTLSB: rtype = R_IA64_EPLTLSB; break;
case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break;
case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
static void
elfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
arelent *bfd_reloc;
ElfNN_Internal_Rela *elf_reloc;
{
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Rela *internal_relocs;
- Elf_Internal_Rela *free_relocs;
+ Elf_Internal_Rela *free_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
bfd_byte *contents;
- bfd_byte *free_contents;
+ bfd_byte *free_contents = NULL;
ElfNN_External_Sym *extsyms;
- ElfNN_External_Sym *free_extsyms;
+ ElfNN_External_Sym *free_extsyms = NULL;
struct elfNN_ia64_link_hash_table *ia64_info;
struct one_fixup *fixups = NULL;
boolean changed_contents = false;
link_info->keep_memory));
if (internal_relocs == NULL)
goto error_return;
- free_relocs = NULL;
+
if (! link_info->keep_memory)
free_relocs = internal_relocs;
}
/* Get the section contents. */
- free_contents = NULL;
if (elf_section_data (sec)->this_hdr.contents != NULL)
contents = elf_section_data (sec)->this_hdr.contents;
else
}
/* Read this BFD's symbols. */
- free_extsyms = NULL;
if (symtab_hdr->contents != NULL)
extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;
else
static boolean
elfNN_ia64_fake_sections (abfd, hdr, sec)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
ElfNN_Internal_Shdr *hdr;
asection *sec;
{
bfd *abfd;
struct bfd_link_info *info;
const Elf_Internal_Sym *sym;
- const char **namep;
- flagword *flagsp;
+ const char **namep ATTRIBUTE_UNUSED;
+ flagword *flagsp ATTRIBUTE_UNUSED;
asection **secp;
bfd_vma *valp;
{
if (sym->st_shndx == SHN_COMMON
&& !info->relocateable
- && sym->st_size <= bfd_get_gp_size (abfd))
+ && sym->st_size <= (unsigned) bfd_get_gp_size (abfd))
{
/* Common symbols less than or equal to -G nn bytes are
automatically put into .sbss. */
static boolean
elfNN_ia64_is_local_label_name (abfd, name)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
const char *name;
{
return name[0] == '.';
static boolean
elfNN_ia64_local_hash_table_init (ht, abfd, new)
struct elfNN_ia64_local_hash_table *ht;
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
new_hash_entry_func new;
{
memset (ht, 0, sizeof(*ht));
struct bfd_link_info *info;
{
struct elfNN_ia64_link_hash_table *ia64_info;
- struct elf_link_hash_entry *h;
asection *s;
if (! _bfd_elf_create_dynamic_sections (abfd, info))
len += 10; /* %p slop */
addr_name = alloca (len);
- sprintf (addr_name, "%p:%lx", abfd, ELFNN_R_SYM (rel->r_info));
+ sprintf (addr_name, "%p:%lx", (void *) abfd, ELFNN_R_SYM (rel->r_info));
/* Collect the canonical entry data for this address. */
loc_h = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
struct bfd_link_info *info;
struct elfNN_ia64_link_hash_table *ia64_info;
{
- asection *got, *srel;
+ asection *got;
bfd *dynobj;
got = ia64_info->got_sec;
static asection *
get_fptr (abfd, info, ia64_info)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
struct elfNN_ia64_link_hash_table *ia64_info;
{
asection *fptr;
static asection *
get_pltoff (abfd, info, ia64_info)
bfd *abfd;
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
struct elfNN_ia64_link_hash_table *ia64_info;
{
asection *pltoff;
struct elfNN_ia64_dyn_sym_info *dyn_i;
int need_entry;
boolean maybe_dynamic;
- int dynrel_type;
+ int dynrel_type = R_IA64_NONE;
if (r_symndx >= symtab_hdr->sh_info)
{
dynrel_type = R_IA64_DIR64LSB;
break;
+ case R_IA64_IPLTMSB:
+ case R_IA64_IPLTLSB:
+ /* Shared objects will always need at least a REL relocation. */
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_IPLTLSB;
+ break;
+
case R_IA64_PCREL22:
case R_IA64_PCREL64I:
case R_IA64_PCREL32MSB:
for (rent = dyn_i->reloc_entries; rent; rent = rent->next)
{
+ int count = rent->count;
+
switch (rent->type)
{
case R_IA64_FPTR64LSB:
if (!dynamic_symbol && !shared)
continue;
break;
+ case R_IA64_IPLTLSB:
+ if (!dynamic_symbol && !shared)
+ continue;
+ /* Use two REL relocations for IPLT relocations
+ against local symbols. */
+ if (!dynamic_symbol)
+ count *= 2;
+ break;
+ default:
+ abort ();
}
- rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * rent->count;
+ rent->srel->_raw_size += sizeof (ElfNN_External_Rela) * count;
}
/* Take care of the GOT and PLT relocations. */
static boolean
elfNN_ia64_adjust_dynamic_symbol (info, h)
- struct bfd_link_info *info;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
struct elf_link_hash_entry *h;
{
/* ??? Undefined symbols with PLT entries should be re-defined
sec->_raw_size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
}
- /* DT_INIT and DT_FINI get function descriptors not raw code addresses.
- Force their symbols to have pltoff entries so we can use those. */
- if (ia64_info->root.dynamic_sections_created)
- {
- struct elf_link_hash_entry *h;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
-
- if (info->init_function
- && (h = elf_link_hash_lookup (elf_hash_table (info),
- info->init_function, false,
- false, false))
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
- {
- dyn_i = get_dyn_sym_info (ia64_info, h, output_bfd, NULL, true);
- dyn_i->want_pltoff = 1;
- }
-
- if (info->fini_function
- && (h = elf_link_hash_lookup (elf_hash_table (info),
- info->fini_function, false,
- false, false))
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
- {
- dyn_i = get_dyn_sym_info (ia64_info, h, output_bfd, NULL, true);
- dyn_i->want_pltoff = 1;
- }
- }
-
/* Allocate the GOT entries. */
if (ia64_info->got_sec)
break;
/* Unsupported / Dynamic relocations. */
-
- case R_IA64_REL32MSB:
- case R_IA64_REL32LSB:
- case R_IA64_REL64MSB:
- case R_IA64_REL64LSB:
-
- case R_IA64_IPLTMSB:
- case R_IA64_IPLTLSB:
- case R_IA64_EPLTMSB:
- case R_IA64_EPLTLSB:
- case R_IA64_COPY:
-
- case R_IA64_SEGBASE:
-
- case R_IA64_TPREL22:
- case R_IA64_TPREL64MSB:
- case R_IA64_TPREL64LSB:
- case R_IA64_LTOFF_TP22:
-
default:
return bfd_reloc_notsupported;
}
if ((! dyn_i->want_plt || is_plt)
&& !dyn_i->pltoff_done)
{
+ bfd_vma gp = _bfd_get_gp_value (abfd);
+
/* Fill in the function descriptor. */
bfd_put_64 (abfd, value, pltoff_sec->contents + dyn_i->pltoff_offset);
- bfd_put_64 (abfd, _bfd_get_gp_value (abfd),
- pltoff_sec->contents + dyn_i->pltoff_offset + 8);
+ bfd_put_64 (abfd, gp, pltoff_sec->contents + dyn_i->pltoff_offset + 8);
/* Install dynamic relocations if needed. */
if (!is_plt && info->shared)
elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
ia64_info->rel_pltoff_sec,
dyn_i->pltoff_offset,
- dyn_r_type, 0, 0);
+ dyn_r_type, 0, value);
elfNN_ia64_install_dyn_reloc (abfd, NULL, pltoff_sec,
ia64_info->rel_pltoff_sec,
dyn_i->pltoff_offset + 8,
- dyn_r_type, 0, 0);
+ dyn_r_type, 0, gp);
}
dyn_i->pltoff_done = 1;
struct bfd_link_info *info;
{
struct elfNN_ia64_link_hash_table *ia64_info;
+ asection *unwind_output_sec;
+
ia64_info = elfNN_ia64_hash_table (info);
/* Make sure we've got ourselves a nice fat __gp value. */
_bfd_set_gp_value (abfd, gp_val);
}
- /* Tricky bits. DT_INIT and DT_FINI use a pltoff entry, which is
- normally initialized in finish_dynamic_sections. Except that
- we need all non-plt pltoff entries to be initialized before
- finish_dynamic_symbols. This because the array of relocations
- used for plt entries (aka DT_JMPREL) begins after all the
- non-plt pltoff relocations. If the order gets confused, we
- munge either the array or the array base. */
- if (ia64_info->root.dynamic_sections_created)
- {
- struct elf_link_hash_entry *h;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- bfd_vma addr;
-
- if (info->init_function
- && (h = elf_link_hash_lookup (elf_hash_table (info),
- info->init_function, false,
- false, false))
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
- {
- dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, false);
- addr = (h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset
- + h->root.u.def.value);
- (void) set_pltoff_entry (abfd, info, dyn_i, addr, false);
- }
-
- if (info->fini_function
- && (h = elf_link_hash_lookup (elf_hash_table (info),
- info->fini_function, false,
- false, false))
- && (h->elf_link_hash_flags & (ELF_LINK_HASH_REF_REGULAR
- | ELF_LINK_HASH_DEF_REGULAR)) != 0)
- {
- dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, false);
- addr = (h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset
- + h->root.u.def.value);
- (void) set_pltoff_entry (abfd, info, dyn_i, addr, false);
- }
- }
-
- /* Invoke the regular ELF backend linker to do all the work. */
- if (!bfd_elfNN_bfd_final_link (abfd, info))
- return false;
-
/* If we're producing a final executable, we need to sort the contents
- of the .IA_64.unwind section. */
+ 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)
{
asection *s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
if (s)
{
- bfd_size_type size = s->output_section->_raw_size;
- char *contents = bfd_malloc (size);
-
- if (contents == NULL)
- return false;
- if (! bfd_get_section_contents (abfd, s->output_section,
- contents, (file_ptr) 0, size))
+ unwind_output_sec = s->output_section;
+ unwind_output_sec->contents
+ = bfd_malloc (unwind_output_sec->_raw_size);
+ if (unwind_output_sec->contents == NULL)
return false;
+ }
+ }
- elfNN_ia64_unwind_entry_compare_bfd = abfd;
- qsort (contents, size / 24, 24, elfNN_ia64_unwind_entry_compare);
+ /* Invoke the regular ELF backend linker to do all the work. */
+ if (!bfd_elfNN_bfd_final_link (abfd, info))
+ return false;
- if (! bfd_set_section_contents (abfd, s->output_section,
- contents, (file_ptr) 0, size))
- return false;
- }
+ if (unwind_output_sec)
+ {
+ elfNN_ia64_unwind_entry_compare_bfd = abfd;
+ qsort (unwind_output_sec->contents, unwind_output_sec->_raw_size / 24,
+ 24, elfNN_ia64_unwind_entry_compare);
+
+ if (! bfd_set_section_contents (abfd, unwind_output_sec,
+ unwind_output_sec->contents, 0,
+ unwind_output_sec->_raw_size))
+ return false;
}
return true;
{
unsigned int dyn_r_type;
long dynindx;
+ bfd_vma addend;
BFD_ASSERT (srel != NULL);
matching RELATIVE relocation. */
dyn_r_type = r_type;
if (dynamic_symbol_p)
- dynindx = h->dynindx;
+ {
+ dynindx = h->dynindx;
+ addend = rel->r_addend;
+ value = 0;
+ }
else
{
switch (r_type)
continue;
}
dynindx = 0;
+ addend = value;
}
elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
srel, rel->r_offset, dyn_r_type,
- dynindx, rel->r_addend);
+ dynindx, addend);
}
/* FALLTHRU */
r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
break;
- case R_IA64_SEGBASE:
-
- case R_IA64_REL32MSB:
- case R_IA64_REL32LSB:
- case R_IA64_REL64MSB:
- case R_IA64_REL64LSB:
-
case R_IA64_IPLTMSB:
case R_IA64_IPLTLSB:
- case R_IA64_EPLTMSB:
- case R_IA64_EPLTLSB:
- case R_IA64_COPY:
+ /* Install a dynamic relocation for this reloc. */
+ if ((dynamic_symbol_p || info->shared)
+ && (input_section->flags & SEC_ALLOC) != 0)
+ {
+ BFD_ASSERT (srel != NULL);
+
+ /* If we don't need dynamic symbol lookup, install two
+ RELATIVE relocations. */
+ if (! dynamic_symbol_p)
+ {
+ unsigned int dyn_r_type;
+
+ if (r_type == R_IA64_IPLTMSB)
+ dyn_r_type = R_IA64_REL64MSB;
+ else
+ dyn_r_type = R_IA64_REL64LSB;
+
+ elfNN_ia64_install_dyn_reloc (output_bfd, info,
+ input_section,
+ srel, rel->r_offset,
+ dyn_r_type, 0, value);
+ elfNN_ia64_install_dyn_reloc (output_bfd, info,
+ input_section,
+ srel, rel->r_offset + 8,
+ dyn_r_type, 0, gp_val);
+ }
+ else
+ elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
+ srel, rel->r_offset, r_type,
+ h->dynindx, rel->r_addend);
+ }
+
+ if (r_type == 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);
+ break;
- case R_IA64_TPREL22:
- case R_IA64_TPREL64MSB:
- case R_IA64_TPREL64LSB:
- case R_IA64_LTOFF_TP22:
default:
r = bfd_reloc_notsupported;
break;
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
- const char *name;
- asection *s;
bfd_elfNN_swap_dyn_in (dynobj, dyncon, &dyn);
dyn.d_un.d_val -= (ia64_info->minplt_entries
* sizeof (ElfNN_External_Rela));
break;
-
- case DT_INIT:
- case DT_FINI:
- {
- struct elf_link_hash_entry *h;
- struct elfNN_ia64_dyn_sym_info *dyn_i;
- const char *which;
-
- if (dyn.d_tag == DT_INIT)
- which = info->init_function;
- else
- which = info->fini_function;
-
- h = elf_link_hash_lookup (elf_hash_table (info), which,
- false, false, false);
- dyn_i = get_dyn_sym_info (ia64_info, h, NULL, NULL, false);
- dyn.d_un.d_ptr = set_pltoff_entry (abfd, info, dyn_i,
- dyn.d_un.d_ptr, 0);
- }
}
bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);