bfd_vma pltoff_offset;
bfd_vma plt_offset;
bfd_vma plt2_offset;
+ bfd_vma tprel_offset;
+ bfd_vma dtpmod_offset;
+ bfd_vma dtprel_offset;
/* The symbol table entry, if any, that this was derrived from. */
struct elf_link_hash_entry *h;
unsigned got_done : 1;
unsigned fptr_done : 1;
unsigned pltoff_done : 1;
+ unsigned tprel_done : 1;
+ unsigned dtpmod_done : 1;
+ unsigned dtprel_done : 1;
/* True for the different kinds of linker data we want created. */
unsigned want_got : 1;
unsigned want_plt : 1;
unsigned want_plt2 : 1;
unsigned want_pltoff : 1;
+ unsigned want_tprel : 1;
+ unsigned want_dtpmod : 1;
+ unsigned want_dtprel : 1;
};
struct elfNN_ia64_local_hash_entry
static boolean is_unwind_section_name
PARAMS ((bfd *abfd, const char *));
static boolean elfNN_ia64_section_from_shdr
- PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));
+ PARAMS ((bfd *, ElfNN_Internal_Shdr *, const char *));
static boolean elfNN_ia64_section_flags
PARAMS ((flagword *, ElfNN_Internal_Shdr *));
static boolean elfNN_ia64_fake_sections
PARAMS ((bfd *abfd, struct bfd_link_info *info,
struct elfNN_ia64_dyn_sym_info *dyn_i,
bfd_vma value, boolean));
+static bfd_vma elfNN_ia64_tprel_base
+ PARAMS ((struct bfd_link_info *info));
+static bfd_vma elfNN_ia64_dtprel_base
+ PARAMS ((struct bfd_link_info *info));
static int elfNN_ia64_unwind_entry_compare
PARAMS ((const PTR, const PTR));
static boolean elfNN_ia64_final_link
IA64_HOWTO (R_IA64_LTOFF22X, "LTOFF22X", 0, false, true),
IA64_HOWTO (R_IA64_LDXMOV, "LDXMOV", 0, false, true),
+ 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_LTOFF_TP22, "LTOFF_TP22", 0, 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_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_LTOFF_DTPREL22, "LTOFF_DTPREL22", 0, false, false),
};
static unsigned char elf_code_to_howto_index[R_IA64_MAX_RELOC_CODE + 1];
case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break;
case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break;
+ case BFD_RELOC_IA64_TPREL14: rtype = R_IA64_TPREL14; break;
case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break;
+ case BFD_RELOC_IA64_TPREL64I: rtype = R_IA64_TPREL64I; break;
case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break;
case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break;
- case BFD_RELOC_IA64_LTOFF_TP22: rtype = R_IA64_LTOFF_TP22; break;
+ case BFD_RELOC_IA64_LTOFF_TPREL22: rtype = R_IA64_LTOFF_TPREL22; break;
+
+ case BFD_RELOC_IA64_DTPMOD64MSB: rtype = R_IA64_DTPMOD64MSB; break;
+ case BFD_RELOC_IA64_DTPMOD64LSB: rtype = R_IA64_DTPMOD64LSB; break;
+ case BFD_RELOC_IA64_LTOFF_DTPMOD22: rtype = R_IA64_LTOFF_DTPMOD22; break;
+
+ case BFD_RELOC_IA64_DTPREL14: rtype = R_IA64_DTPREL14; break;
+ case BFD_RELOC_IA64_DTPREL22: rtype = R_IA64_DTPREL22; break;
+ case BFD_RELOC_IA64_DTPREL64I: rtype = R_IA64_DTPREL64I; break;
+ case BFD_RELOC_IA64_DTPREL32MSB: rtype = R_IA64_DTPREL32MSB; break;
+ case BFD_RELOC_IA64_DTPREL32LSB: rtype = R_IA64_DTPREL32LSB; break;
+ case BFD_RELOC_IA64_DTPREL64MSB: rtype = R_IA64_DTPREL64MSB; break;
+ case BFD_RELOC_IA64_DTPREL64LSB: rtype = R_IA64_DTPREL64LSB; break;
+ case BFD_RELOC_IA64_LTOFF_DTPREL22: rtype = R_IA64_LTOFF_DTPREL22; break;
default: return 0;
}
};
Elf_Internal_Shdr *symtab_hdr;
- Elf_Internal_Shdr *shndx_hdr;
Elf_Internal_Rela *internal_relocs;
- Elf_Internal_Rela *free_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
bfd_byte *contents;
- bfd_byte *free_contents = NULL;
- ElfNN_External_Sym *extsyms;
- ElfNN_External_Sym *free_extsyms = NULL;
- Elf_External_Sym_Shndx *shndx_buf = NULL;
+ Elf_Internal_Sym *isymbuf = NULL;
struct elfNN_ia64_link_hash_table *ia64_info;
struct one_fixup *fixups = NULL;
boolean changed_contents = false;
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
link_info->keep_memory));
if (internal_relocs == NULL)
- goto error_return;
-
- if (! link_info->keep_memory)
- free_relocs = internal_relocs;
+ return false;
ia64_info = elfNN_ia64_hash_table (link_info);
irelend = internal_relocs + sec->reloc_count;
/* No branch-type relocations. */
if (irel == irelend)
{
- if (free_relocs != NULL)
- free (free_relocs);
+ if (elf_section_data (sec)->relocs != internal_relocs)
+ free (internal_relocs);
return true;
}
contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
if (contents == NULL)
goto error_return;
- free_contents = contents;
if (! bfd_get_section_contents (abfd, sec, contents,
(file_ptr) 0, sec->_raw_size))
goto error_return;
}
- /* Read this BFD's local symbols. */
- if (symtab_hdr->contents != NULL)
- extsyms = (ElfNN_External_Sym *) symtab_hdr->contents;
- else
- {
- bfd_size_type amt;
-
- amt = symtab_hdr->sh_info * sizeof (ElfNN_External_Sym);
- extsyms = (ElfNN_External_Sym *) bfd_malloc (amt);
- if (extsyms == NULL)
- goto error_return;
- free_extsyms = extsyms;
- if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread (extsyms, amt, abfd) != amt)
- goto error_return;
- }
-
- shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (shndx_hdr->sh_size != 0)
- {
- bfd_size_type amt;
-
- amt = symtab_hdr->sh_info * sizeof (Elf_External_Sym_Shndx);
- shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
- if (shndx_buf == NULL)
- goto error_return;
- if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
- || bfd_bread (shndx_buf, amt, abfd) != amt)
- goto error_return;
- }
-
for (; irel < irelend; irel++)
{
bfd_vma symaddr, reladdr, trampoff, toff, roff;
- Elf_Internal_Sym isym;
asection *tsec;
struct one_fixup *f;
bfd_size_type amt;
/* Get the value of the symbol referred to by the reloc. */
if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
- ElfNN_External_Sym *esym;
- Elf_External_Sym_Shndx *shndx;
-
/* A local symbol. */
- esym = extsyms + ELFNN_R_SYM (irel->r_info);
- shndx = shndx_buf + (shndx_buf ? ELFNN_R_SYM (irel->r_info) : 0);
- bfd_elfNN_swap_symbol_in (abfd, esym, shndx, &isym);
- if (isym.st_shndx == SHN_UNDEF)
+ Elf_Internal_Sym *isym;
+
+ /* Read this BFD's local symbols. */
+ if (isymbuf == NULL)
+ {
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == 0)
+ goto error_return;
+ }
+
+ isym = isymbuf + ELF64_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)
+ else if (isym->st_shndx == SHN_ABS)
tsec = bfd_abs_section_ptr;
- else if (isym.st_shndx == SHN_COMMON)
+ else if (isym->st_shndx == SHN_COMMON)
tsec = bfd_com_section_ptr;
- else if (isym.st_shndx == SHN_IA_64_ANSI_COMMON)
+ else if (isym->st_shndx == SHN_IA_64_ANSI_COMMON)
tsec = bfd_com_section_ptr;
else
- tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
- toff = isym.st_value;
+ toff = isym->st_value;
}
else
{
free (f);
}
- if (changed_relocs)
- elf_section_data (sec)->relocs = internal_relocs;
- else if (free_relocs != NULL)
- free (free_relocs);
-
- if (changed_contents)
- elf_section_data (sec)->this_hdr.contents = contents;
- else if (free_contents != NULL)
+ if (isymbuf != NULL
+ && symtab_hdr->contents != (unsigned char *) isymbuf)
{
if (! link_info->keep_memory)
- free (free_contents);
+ free (isymbuf);
else
{
- /* Cache the section contents for elf_link_input_bfd. */
- elf_section_data (sec)->this_hdr.contents = contents;
+ /* Cache the symbols for elf_link_input_bfd. */
+ symtab_hdr->contents = (unsigned char *) isymbuf;
}
}
- if (shndx_buf != NULL)
- free (shndx_buf);
-
- if (free_extsyms != NULL)
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
{
- if (! link_info->keep_memory)
- free (free_extsyms);
+ if (!changed_contents && !link_info->keep_memory)
+ free (contents);
else
{
- /* Cache the symbols for elf_link_input_bfd. */
- symtab_hdr->contents = (unsigned char *) extsyms;
+ /* Cache the section contents for elf_link_input_bfd. */
+ elf_section_data (sec)->this_hdr.contents = contents;
}
}
+ if (elf_section_data (sec)->relocs != internal_relocs)
+ {
+ if (!changed_relocs)
+ free (internal_relocs);
+ else
+ elf_section_data (sec)->relocs = internal_relocs;
+ }
+
*again = changed_contents || changed_relocs;
return true;
error_return:
- if (free_relocs != NULL)
- free (free_relocs);
- if (free_contents != NULL)
- free (free_contents);
- if (shndx_buf != NULL)
- free (shndx_buf);
- if (free_extsyms != NULL)
- free (free_extsyms);
+ if (isymbuf != NULL && (unsigned char *) isymbuf != symtab_hdr->contents)
+ free (isymbuf);
+ if (contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != contents)
+ free (contents);
+ if (internal_relocs != NULL
+ && elf_section_data (sec)->relocs != internal_relocs)
+ free (internal_relocs);
return false;
}
\f
elfNN_ia64_section_from_shdr (abfd, hdr, name)
bfd *abfd;
ElfNN_Internal_Shdr *hdr;
- char *name;
+ const char *name;
{
asection *newsect;
switch (hdr->sh_type)
{
case SHT_IA_64_UNWIND:
- case SHT_INIT_ARRAY:
- case SHT_FINI_ARRAY:
- case SHT_PREINIT_ARRAY:
case SHT_IA_64_HP_OPT_ANOT:
break;
}
else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
hdr->sh_type = SHT_IA_64_EXT;
- else if (strcmp (name, ".init_array") == 0)
- hdr->sh_type = SHT_INIT_ARRAY;
- else if (strcmp (name, ".fini_array") == 0)
- hdr->sh_type = SHT_FINI_ARRAY;
- else if (strcmp (name, ".preinit_array") == 0)
- hdr->sh_type = SHT_PREINIT_ARRAY;
else if (strcmp (name, ".HP.opt_annot") == 0)
hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
else if (strcmp (name, ".reloc") == 0)
= (struct elfNN_ia64_dyn_sym_traverse_data *) xdata;
struct elfNN_ia64_dyn_sym_info *dyn_i;
+ if (entry->root.root.type == bfd_link_hash_warning)
+ entry = (struct elfNN_ia64_link_hash_entry *) entry->root.root.u.i.link;
+
for (dyn_i = entry->info; dyn_i; dyn_i = dyn_i->next)
if (! (*data->func) (dyn_i, data->data))
return false;
NEED_FULL_PLT = 16,
NEED_DYNREL = 32,
NEED_LTOFF_FPTR = 64,
+ NEED_TPREL = 128,
+ NEED_DTPMOD = 256,
+ NEED_DTPREL = 512
};
struct elf_link_hash_entry *h = NULL;
need_entry = 0;
switch (ELFNN_R_TYPE (rel->r_info))
{
- case R_IA64_TPREL22:
case R_IA64_TPREL64MSB:
case R_IA64_TPREL64LSB:
- case R_IA64_LTOFF_TP22:
- return false;
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_TPREL64LSB;
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_IA64_LTOFF_TPREL22:
+ need_entry = NEED_TPREL;
+ if (info->shared)
+ info->flags |= DF_STATIC_TLS;
+ break;
+
+ case R_IA64_DTPREL64MSB:
+ case R_IA64_DTPREL64LSB:
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_DTPREL64LSB;
+ break;
+
+ case R_IA64_LTOFF_DTPREL22:
+ need_entry = NEED_DTPREL;
+ break;
+
+ case R_IA64_DTPMOD64MSB:
+ case R_IA64_DTPMOD64LSB:
+ if (info->shared || maybe_dynamic)
+ need_entry = NEED_DYNREL;
+ dynrel_type = R_IA64_DTPMOD64LSB;
+ break;
+
+ case R_IA64_LTOFF_DTPMOD22:
+ need_entry = NEED_DTPMOD;
+ break;
case R_IA64_LTOFF_FPTR22:
case R_IA64_LTOFF_FPTR64I:
dyn_i->h = h;
/* Create what's needed. */
- if (need_entry & NEED_GOT)
+ if (need_entry & (NEED_GOT | NEED_TPREL | NEED_DTPMOD | NEED_DTPREL))
{
if (!got)
{
if (!got)
return false;
}
- dyn_i->want_got = 1;
+ if (need_entry & NEED_GOT)
+ dyn_i->want_got = 1;
+ if (need_entry & NEED_TPREL)
+ dyn_i->want_tprel = 1;
+ if (need_entry & NEED_DTPMOD)
+ dyn_i->want_dtpmod = 1;
+ if (need_entry & NEED_DTPREL)
+ dyn_i->want_dtprel = 1;
}
if (need_entry & NEED_FPTR)
{
dyn_i->got_offset = x->ofs;
x->ofs += 8;
}
+ if (dyn_i->want_tprel)
+ {
+ dyn_i->tprel_offset = x->ofs;
+ x->ofs += 8;
+ }
+ if (dyn_i->want_dtpmod)
+ {
+ dyn_i->dtpmod_offset = x->ofs;
+ x->ofs += 8;
+ }
+ if (dyn_i->want_dtprel)
+ {
+ dyn_i->dtprel_offset = x->ofs;
+ x->ofs += 8;
+ }
return true;
}
if (!dynamic_symbol)
count *= 2;
break;
+ case R_IA64_TPREL64LSB:
+ case R_IA64_DTPREL64LSB:
+ case R_IA64_DTPMOD64LSB:
+ break;
default:
abort ();
}
if (((dynamic_symbol || shared) && dyn_i->want_got)
|| (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 || shared) && dyn_i->want_dtpmod)
+ 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)
{
/* Instruction relocations. */
- case R_IA64_IMM14: opnd = IA64_OPND_IMM14; break;
+ case R_IA64_IMM14:
+ case R_IA64_TPREL14:
+ case R_IA64_DTPREL14:
+ opnd = IA64_OPND_IMM14;
+ break;
case R_IA64_PCREL21F: opnd = IA64_OPND_TGT25; break;
case R_IA64_PCREL21M: opnd = IA64_OPND_TGT25b; break;
case R_IA64_PLTOFF22:
case R_IA64_PCREL22:
case R_IA64_LTOFF_FPTR22:
+ case R_IA64_TPREL22:
+ case R_IA64_DTPREL22:
+ case R_IA64_LTOFF_TPREL22:
+ case R_IA64_LTOFF_DTPMOD22:
+ case R_IA64_LTOFF_DTPREL22:
opnd = IA64_OPND_IMM22;
break;
case R_IA64_PCREL64I:
case R_IA64_FPTR64I:
case R_IA64_LTOFF_FPTR64I:
+ case R_IA64_TPREL64I:
+ case R_IA64_DTPREL64I:
opnd = IA64_OPND_IMMU64;
break;
case R_IA64_SEGREL32MSB:
case R_IA64_SECREL32MSB:
case R_IA64_LTV32MSB:
+ case R_IA64_DTPREL32MSB:
size = 4; bigendian = 1;
break;
case R_IA64_SEGREL32LSB:
case R_IA64_SECREL32LSB:
case R_IA64_LTV32LSB:
+ case R_IA64_DTPREL32LSB:
size = 4; bigendian = 0;
break;
case R_IA64_SEGREL64MSB:
case R_IA64_SECREL64MSB:
case R_IA64_LTV64MSB:
+ case R_IA64_TPREL64MSB:
+ case R_IA64_DTPMOD64MSB:
+ case R_IA64_DTPREL64MSB:
size = 8; bigendian = 1;
break;
case R_IA64_SEGREL64LSB:
case R_IA64_SECREL64LSB:
case R_IA64_LTV64LSB:
+ case R_IA64_TPREL64LSB:
+ case R_IA64_DTPMOD64LSB:
+ case R_IA64_DTPREL64LSB:
size = 8; bigendian = 0;
break;
{
struct elfNN_ia64_link_hash_table *ia64_info;
asection *got_sec;
+ boolean done;
+ bfd_vma got_offset;
ia64_info = elfNN_ia64_hash_table (info);
got_sec = ia64_info->got_sec;
- BFD_ASSERT ((dyn_i->got_offset & 7) == 0);
-
- if (! dyn_i->got_done)
+ switch (dyn_r_type)
{
+ case R_IA64_TPREL64LSB:
+ done = dyn_i->tprel_done;
+ dyn_i->tprel_done = true;
+ got_offset = dyn_i->tprel_offset;
+ break;
+ case R_IA64_DTPMOD64LSB:
+ done = dyn_i->dtpmod_done;
+ dyn_i->dtpmod_done = true;
+ got_offset = dyn_i->dtpmod_offset;
+ break;
+ case R_IA64_DTPREL64LSB:
+ done = dyn_i->dtprel_done;
+ dyn_i->dtprel_done = true;
+ got_offset = dyn_i->dtprel_offset;
+ break;
+ default:
+ done = dyn_i->got_done;
dyn_i->got_done = true;
+ got_offset = dyn_i->got_offset;
+ break;
+ }
+
+ BFD_ASSERT ((got_offset & 7) == 0);
+ if (! done)
+ {
/* Store the target address in the linkage table entry. */
- bfd_put_64 (abfd, value, got_sec->contents + dyn_i->got_offset);
+ bfd_put_64 (abfd, value, got_sec->contents + got_offset);
/* Install a dynamic relocation if needed. */
- if (info->shared
+ if ((info->shared && 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))
{
- if (dynindx == -1)
+ if (dynindx == -1
+ && dyn_r_type != R_IA64_TPREL64LSB
+ && dyn_r_type != R_IA64_DTPMOD64LSB
+ && dyn_r_type != R_IA64_DTPREL64LSB)
{
dyn_r_type = R_IA64_REL64LSB;
dynindx = 0;
case R_IA64_FPTR64LSB:
dyn_r_type = R_IA64_FPTR64MSB;
break;
+ case R_IA64_TPREL64LSB:
+ dyn_r_type = R_IA64_TPREL64MSB;
+ break;
+ case R_IA64_DTPMOD64LSB:
+ dyn_r_type = R_IA64_DTPMOD64MSB;
+ break;
+ case R_IA64_DTPREL64LSB:
+ dyn_r_type = R_IA64_DTPREL64MSB;
+ break;
default:
BFD_ASSERT (false);
break;
elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
ia64_info->rel_got_sec,
- dyn_i->got_offset, dyn_r_type,
+ got_offset, dyn_r_type,
dynindx, addend);
}
}
/* Return the address of the linkage table entry. */
value = (got_sec->output_section->vma
+ got_sec->output_offset
- + dyn_i->got_offset);
+ + got_offset);
return value;
}
return value;
}
+/* Return the base VMA address which should be subtracted from real addresses
+ when resolving @tprel() relocation.
+ Main program TLS (whose template starts at PT_TLS p_vaddr)
+ is assigned offset round(16, PT_TLS p_align). */
+
+static bfd_vma
+elfNN_ia64_tprel_base (info)
+ struct bfd_link_info *info;
+{
+ struct elf_link_tls_segment *tls_segment
+ = elf_hash_table (info)->tls_segment;
+
+ BFD_ASSERT (tls_segment != NULL);
+ return (tls_segment->start
+ - align_power ((bfd_vma) 16, tls_segment->align));
+}
+
+/* Return the base VMA address which should be subtracted from real addresses
+ when resolving @dtprel() relocation.
+ This is PT_TLS segment p_vaddr. */
+
+static bfd_vma
+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;
+}
+
/* Called through qsort to sort the .IA_64.unwind section during a
non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
to the output bfd so we can do proper endianness frobbing. */
elf_section_data(input_section->output_section)
->this_hdr.sh_flags |= flags;
+ return true;
}
gp_val = _bfd_get_gp_value (output_bfd);
ret_val = false;
continue;
}
+
howto = lookup_howto (r_type);
r_symndx = ELFNN_R_SYM (rel->r_info);
-
- if (info->relocateable)
- {
- /* This is a relocateable link. We don't have to change
- anything, unless the reloc is against a section symbol,
- in which case we have to adjust according to where the
- section symbol winds up in the output section. */
- if (r_symndx < symtab_hdr->sh_info)
- {
- sym = local_syms + r_symndx;
- if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- {
- sym_sec = local_sections[r_symndx];
- rel->r_addend += sym_sec->output_offset;
- }
- }
- continue;
- }
-
- /* This is a final link. */
-
h = NULL;
sym = NULL;
sym_sec = NULL;
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);
+ break;
+
+ case R_IA64_DTPREL14:
+ case R_IA64_DTPREL22:
+ case R_IA64_DTPREL64I:
+ value -= elfNN_ia64_dtprel_base (info);
+ r = elfNN_ia64_install_value (output_bfd, hit_addr, value, r_type);
+ break;
+
+ case R_IA64_LTOFF_TPREL22:
+ case R_IA64_LTOFF_DTPMOD22:
+ case R_IA64_LTOFF_DTPREL22:
+ {
+ int got_r_type;
+
+ switch (r_type)
+ {
+ default:
+ case R_IA64_LTOFF_TPREL22:
+ if (!dynamic_symbol_p && !info->shared)
+ value -= elfNN_ia64_tprel_base (info);
+ got_r_type = R_IA64_TPREL64LSB;
+ break;
+ case R_IA64_LTOFF_DTPMOD22:
+ if (!dynamic_symbol_p && !info->shared)
+ value = 1;
+ got_r_type = R_IA64_DTPMOD64LSB;
+ break;
+ case R_IA64_LTOFF_DTPREL22:
+ if (!dynamic_symbol_p)
+ value -= elfNN_ia64_dtprel_base (info);
+ got_r_type = R_IA64_DTPREL64LSB;
+ break;
+ }
+ dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, false);
+ value = set_got_entry (input_bfd, info, dyn_i,
+ (h ? h->dynindx : -1), rel->r_addend,
+ value, got_r_type);
+ value -= gp_val;
+ r = elfNN_ia64_install_value (output_bfd, hit_addr, value,
+ r_type);
+ }
+ break;
+
default:
r = bfd_reloc_notsupported;
break;
#define elf_backend_copy_indirect_symbol elfNN_ia64_hash_copy_indirect
#define elf_backend_hide_symbol elfNN_ia64_hash_hide_symbol
#define elf_backend_reloc_type_class elfNN_ia64_reloc_type_class
+#define elf_backend_rela_normal 1
#include "elfNN-target.h"