* elf64-alpha.c (alpha_elf_dynamic_symbol_p): Undef weak symbols
are always dynamic. (elf64_alpha_calc_dynrel_sizes): Allow enough room for RELATIVE .got relocs in -Bsymbolic shared objects.
This commit is contained in:
parent
157a2e242f
commit
382fab1a7a
2 changed files with 230 additions and 189 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
Sat Aug 8 15:15:30 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
|
* elf64-alpha.c (alpha_elf_dynamic_symbol_p): Undef weak symbols
|
||||||
|
are always dynamic.
|
||||||
|
(elf64_alpha_calc_dynrel_sizes): Allow enough room for RELATIVE
|
||||||
|
.got relocs in -Bsymbolic shared objects.
|
||||||
|
|
||||||
start-sanitize-armelf
|
start-sanitize-armelf
|
||||||
Wed Aug 5 15:48:08 1998 Nick Clifton <nickc@cygnus.com>
|
Wed Aug 5 15:48:08 1998 Nick Clifton <nickc@cygnus.com>
|
||||||
|
|
||||||
|
|
|
@ -229,7 +229,8 @@ struct alpha_elf_link_hash_table
|
||||||
(((info)->shared && !(info)->symbolic && (h)->dynindx != -1) \
|
(((info)->shared && !(info)->symbolic && (h)->dynindx != -1) \
|
||||||
|| (((h)->elf_link_hash_flags \
|
|| (((h)->elf_link_hash_flags \
|
||||||
& (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) \
|
& (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) \
|
||||||
== (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)))
|
== (ELF_LINK_HASH_DEF_DYNAMIC | ELF_LINK_HASH_REF_REGULAR)) \
|
||||||
|
|| (h)->root.type == bfd_link_hash_undefweak)
|
||||||
|
|
||||||
/* Create an entry in a Alpha ELF linker hash table. */
|
/* Create an entry in a Alpha ELF linker hash table. */
|
||||||
|
|
||||||
|
@ -1043,9 +1044,9 @@ struct alpha_relax_info
|
||||||
bfd_vma gp;
|
bfd_vma gp;
|
||||||
bfd *gotobj;
|
bfd *gotobj;
|
||||||
asection *tsec;
|
asection *tsec;
|
||||||
Elf_Internal_Sym *elfsym;
|
|
||||||
struct alpha_elf_link_hash_entry *h;
|
struct alpha_elf_link_hash_entry *h;
|
||||||
struct alpha_elf_got_entry *gotent;
|
struct alpha_elf_got_entry *gotent;
|
||||||
|
unsigned char other;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Elf_Internal_Rela * elf64_alpha_relax_with_lituse
|
static Elf_Internal_Rela * elf64_alpha_relax_with_lituse
|
||||||
|
@ -1282,12 +1283,12 @@ elf64_alpha_relax_opt_call (info, symval)
|
||||||
|
|
||||||
/* If the symbol is marked NOPV, we are being told the function never
|
/* If the symbol is marked NOPV, we are being told the function never
|
||||||
needs its procedure value. */
|
needs its procedure value. */
|
||||||
if (info->elfsym->st_other == STO_ALPHA_NOPV)
|
if (info->other == STO_ALPHA_NOPV)
|
||||||
return symval;
|
return symval;
|
||||||
|
|
||||||
/* If the symbol is marked STD_GP, we are being told the function does
|
/* If the symbol is marked STD_GP, we are being told the function does
|
||||||
a normal ldgp in the first two words. */
|
a normal ldgp in the first two words. */
|
||||||
else if (info->elfsym->st_other == STO_ALPHA_STD_GPLOAD)
|
else if (info->other == STO_ALPHA_STD_GPLOAD)
|
||||||
;
|
;
|
||||||
|
|
||||||
/* Otherwise, we may be able to identify a GP load in the first two
|
/* Otherwise, we may be able to identify a GP load in the first two
|
||||||
|
@ -1298,14 +1299,23 @@ elf64_alpha_relax_opt_call (info, symval)
|
||||||
bfd_vma ofs;
|
bfd_vma ofs;
|
||||||
|
|
||||||
/* Load the relocations from the section that the target symbol is in. */
|
/* Load the relocations from the section that the target symbol is in. */
|
||||||
tsec_relocs = (_bfd_elf64_link_read_relocs
|
if (info->sec == info->tsec)
|
||||||
(info->abfd, info->tsec, (PTR) NULL,
|
{
|
||||||
(Elf_Internal_Rela *) NULL,
|
tsec_relocs = info->relocs;
|
||||||
info->link_info->keep_memory));
|
tsec_relend = info->relend;
|
||||||
if (tsec_relocs == NULL)
|
tsec_free = NULL;
|
||||||
return 0;
|
}
|
||||||
tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
|
else
|
||||||
tsec_relend = tsec_relocs + info->tsec->reloc_count;
|
{
|
||||||
|
tsec_relocs = (_bfd_elf64_link_read_relocs
|
||||||
|
(info->abfd, info->tsec, (PTR) NULL,
|
||||||
|
(Elf_Internal_Rela *) NULL,
|
||||||
|
info->link_info->keep_memory));
|
||||||
|
if (tsec_relocs == NULL)
|
||||||
|
return 0;
|
||||||
|
tsec_relend = tsec_relocs + info->tsec->reloc_count;
|
||||||
|
tsec_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
|
||||||
|
}
|
||||||
|
|
||||||
/* Recover the symbol's offset within the section. */
|
/* Recover the symbol's offset within the section. */
|
||||||
ofs = (symval - info->tsec->output_section->vma
|
ofs = (symval - info->tsec->output_section->vma
|
||||||
|
@ -1527,7 +1537,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
|
|
||||||
info.h = NULL;
|
info.h = NULL;
|
||||||
info.gotent = local_got_entries[ELF64_R_SYM(irel->r_info)];
|
info.gotent = local_got_entries[ELF64_R_SYM(irel->r_info)];
|
||||||
info.elfsym = &isym;
|
info.other = isym.st_other;
|
||||||
symval = isym.st_value;
|
symval = isym.st_value;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1555,7 +1565,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
info.h = h;
|
info.h = h;
|
||||||
info.gotent = gotent;
|
info.gotent = gotent;
|
||||||
info.tsec = h->root.root.u.def.section;
|
info.tsec = h->root.root.u.def.section;
|
||||||
info.elfsym = &((elf_symbol_type *) h)->internal_elf_sym;
|
info.other = h->root.other;
|
||||||
symval = h->root.root.u.def.value;
|
symval = h->root.root.u.def.value;
|
||||||
}
|
}
|
||||||
symval += info.tsec->output_section->vma + info.tsec->output_offset;
|
symval += info.tsec->output_section->vma + info.tsec->output_offset;
|
||||||
|
@ -1618,6 +1628,8 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*again = info.changed_contents || info.changed_relocs;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error_return:
|
error_return:
|
||||||
|
@ -2279,7 +2291,7 @@ elf64_alpha_output_extsym (h, data)
|
||||||
{
|
{
|
||||||
output_section = sec->output_section;
|
output_section = sec->output_section;
|
||||||
if (output_section != NULL)
|
if (output_section != NULL)
|
||||||
h->esym.asym.value = (h->root.plt_offset
|
h->esym.asym.value = (h->root.plt.offset
|
||||||
+ sec->output_offset
|
+ sec->output_offset
|
||||||
+ output_section->vma);
|
+ output_section->vma);
|
||||||
else
|
else
|
||||||
|
@ -2636,7 +2648,7 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
|
||||||
if (s->_raw_size == 0)
|
if (s->_raw_size == 0)
|
||||||
s->_raw_size = PLT_HEADER_SIZE;
|
s->_raw_size = PLT_HEADER_SIZE;
|
||||||
|
|
||||||
h->plt_offset = s->_raw_size;
|
h->plt.offset = s->_raw_size;
|
||||||
s->_raw_size += PLT_ENTRY_SIZE;
|
s->_raw_size += PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* If this symbol is not defined in a regular file, and we are not
|
/* If this symbol is not defined in a regular file, and we are not
|
||||||
|
@ -2646,7 +2658,7 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
|
||||||
if (!info->shared)
|
if (!info->shared)
|
||||||
{
|
{
|
||||||
h->root.u.def.section = s;
|
h->root.u.def.section = s;
|
||||||
h->root.u.def.value = h->plt_offset;
|
h->root.u.def.value = h->plt.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We also need a JMP_SLOT entry in the .rela.plt section. */
|
/* We also need a JMP_SLOT entry in the .rela.plt section. */
|
||||||
|
@ -2759,6 +2771,7 @@ elf64_alpha_can_merge_gots (a, b)
|
||||||
bfd *a, *b;
|
bfd *a, *b;
|
||||||
{
|
{
|
||||||
int total = alpha_elf_tdata (a)->total_got_entries;
|
int total = alpha_elf_tdata (a)->total_got_entries;
|
||||||
|
bfd *bsub;
|
||||||
|
|
||||||
/* Trivial quick fallout test. */
|
/* Trivial quick fallout test. */
|
||||||
if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES)
|
if (total + alpha_elf_tdata (b)->total_got_entries <= MAX_GOT_ENTRIES)
|
||||||
|
@ -2771,39 +2784,40 @@ elf64_alpha_can_merge_gots (a, b)
|
||||||
/* Failing the common trivial comparison, we must effectively
|
/* Failing the common trivial comparison, we must effectively
|
||||||
perform the merge. Not actually performing the merge means that
|
perform the merge. Not actually performing the merge means that
|
||||||
we don't have to store undo information in case we fail. */
|
we don't have to store undo information in case we fail. */
|
||||||
{
|
for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
|
||||||
struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes(b);
|
{
|
||||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata(b)->symtab_hdr;
|
struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes (bsub);
|
||||||
int i, n;
|
Elf_Internal_Shdr *symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
|
||||||
|
int i, n;
|
||||||
|
|
||||||
n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
|
n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
struct alpha_elf_got_entry *ae, *be;
|
struct alpha_elf_got_entry *ae, *be;
|
||||||
struct alpha_elf_link_hash_entry *h;
|
struct alpha_elf_link_hash_entry *h;
|
||||||
|
|
||||||
h = hashes[i];
|
h = hashes[i];
|
||||||
while (h->root.root.type == bfd_link_hash_indirect
|
while (h->root.root.type == bfd_link_hash_indirect
|
||||||
|| h->root.root.type == bfd_link_hash_warning)
|
|| h->root.root.type == bfd_link_hash_warning)
|
||||||
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
|
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
|
||||||
|
|
||||||
for (be = h->got_entries; be ; be = be->next)
|
for (be = h->got_entries; be ; be = be->next)
|
||||||
{
|
{
|
||||||
if (be->use_count == 0)
|
if (be->use_count == 0)
|
||||||
continue;
|
continue;
|
||||||
if (be->gotobj != b)
|
if (be->gotobj != b)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (ae = h->got_entries; ae ; ae = ae->next)
|
for (ae = h->got_entries; ae ; ae = ae->next)
|
||||||
if (ae->gotobj == a && ae->addend == be->addend)
|
if (ae->gotobj == a && ae->addend == be->addend)
|
||||||
goto global_found;
|
goto global_found;
|
||||||
|
|
||||||
if (++total > MAX_GOT_ENTRIES)
|
if (++total > MAX_GOT_ENTRIES)
|
||||||
return false;
|
return false;
|
||||||
global_found:;
|
global_found:;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2814,79 +2828,91 @@ static void
|
||||||
elf64_alpha_merge_gots (a, b)
|
elf64_alpha_merge_gots (a, b)
|
||||||
bfd *a, *b;
|
bfd *a, *b;
|
||||||
{
|
{
|
||||||
int total = alpha_elf_tdata(a)->total_got_entries;
|
int total = alpha_elf_tdata (a)->total_got_entries;
|
||||||
|
bfd *bsub;
|
||||||
|
|
||||||
/* Remember local expansion. */
|
/* Remember local expansion. */
|
||||||
{
|
{
|
||||||
int e = alpha_elf_tdata(b)->n_local_got_entries;
|
int e = alpha_elf_tdata (b)->n_local_got_entries;
|
||||||
total += e;
|
total += e;
|
||||||
alpha_elf_tdata(a)->n_local_got_entries += e;
|
alpha_elf_tdata (a)->n_local_got_entries += e;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Let the local .got entries know they are part of a new subsegment. */
|
for (bsub = b; bsub ; bsub = alpha_elf_tdata (bsub)->in_got_link_next)
|
||||||
{
|
{
|
||||||
struct alpha_elf_got_entry **local_got_entries;
|
struct alpha_elf_got_entry **local_got_entries;
|
||||||
local_got_entries = alpha_elf_tdata(b)->local_got_entries;
|
struct alpha_elf_link_hash_entry **hashes;
|
||||||
if (local_got_entries)
|
Elf_Internal_Shdr *symtab_hdr;
|
||||||
{
|
int i, n;
|
||||||
int i, n;
|
|
||||||
|
|
||||||
n = elf_tdata(b)->symtab_hdr.sh_info;
|
/* Let the local .got entries know they are part of a new subsegment. */
|
||||||
for (i = 0; i < n; ++i)
|
local_got_entries = alpha_elf_tdata (bsub)->local_got_entries;
|
||||||
{
|
if (local_got_entries)
|
||||||
struct alpha_elf_got_entry *gotent;
|
{
|
||||||
for (gotent = local_got_entries[i]; gotent; gotent = gotent->next)
|
n = elf_tdata (bsub)->symtab_hdr.sh_info;
|
||||||
gotent->gotobj = a;
|
for (i = 0; i < n; ++i)
|
||||||
}
|
{
|
||||||
}
|
struct alpha_elf_got_entry *ent;
|
||||||
}
|
for (ent = local_got_entries[i]; ent; ent = ent->next)
|
||||||
|
ent->gotobj = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Merge the global .got entries. */
|
/* Merge the global .got entries. */
|
||||||
{
|
hashes = alpha_elf_sym_hashes (bsub);
|
||||||
struct alpha_elf_link_hash_entry **hashes = alpha_elf_sym_hashes(b);
|
symtab_hdr = &elf_tdata (bsub)->symtab_hdr;
|
||||||
Elf_Internal_Shdr *symtab_hdr = &elf_tdata(b)->symtab_hdr;
|
|
||||||
int i, n;
|
|
||||||
|
|
||||||
n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
|
n = symtab_hdr->sh_size / symtab_hdr->sh_entsize - symtab_hdr->sh_info;
|
||||||
for (i = 0; i < n; ++i)
|
for (i = 0; i < n; ++i)
|
||||||
{
|
{
|
||||||
struct alpha_elf_got_entry *ae, *be, **pbe, **start;
|
struct alpha_elf_got_entry *ae, *be, **pbe, **start;
|
||||||
struct alpha_elf_link_hash_entry *h;
|
struct alpha_elf_link_hash_entry *h;
|
||||||
|
|
||||||
h = hashes[i];
|
h = hashes[i];
|
||||||
while (h->root.root.type == bfd_link_hash_indirect
|
while (h->root.root.type == bfd_link_hash_indirect
|
||||||
|| h->root.root.type == bfd_link_hash_warning)
|
|| h->root.root.type == bfd_link_hash_warning)
|
||||||
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
|
h = (struct alpha_elf_link_hash_entry *)h->root.root.u.i.link;
|
||||||
|
|
||||||
start = &h->got_entries;
|
start = &h->got_entries;
|
||||||
for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
|
for (pbe = start, be = *start; be ; pbe = &be->next, be = be->next)
|
||||||
{
|
{
|
||||||
if (be->use_count == 0)
|
if (be->use_count == 0)
|
||||||
{
|
{
|
||||||
*pbe = be->next;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (be->gotobj != b)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (ae = *start; ae ; ae = ae->next)
|
|
||||||
if (ae->gotobj == a && ae->addend == be->addend)
|
|
||||||
{
|
|
||||||
ae->flags |= be->flags;
|
|
||||||
ae->use_count += be->use_count;
|
|
||||||
*pbe = be->next;
|
*pbe = be->next;
|
||||||
goto global_found;
|
continue;
|
||||||
}
|
}
|
||||||
be->gotobj = a;
|
if (be->gotobj != b)
|
||||||
total += 1;
|
continue;
|
||||||
|
|
||||||
global_found:;
|
for (ae = *start; ae ; ae = ae->next)
|
||||||
}
|
if (ae->gotobj == a && ae->addend == be->addend)
|
||||||
}
|
{
|
||||||
|
ae->flags |= be->flags;
|
||||||
|
ae->use_count += be->use_count;
|
||||||
|
*pbe = be->next;
|
||||||
|
goto global_found;
|
||||||
|
}
|
||||||
|
be->gotobj = a;
|
||||||
|
total += 1;
|
||||||
|
|
||||||
|
global_found:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
alpha_elf_tdata (bsub)->gotobj = a;
|
||||||
|
}
|
||||||
|
alpha_elf_tdata (a)->total_got_entries = total;
|
||||||
|
|
||||||
|
/* Merge the two in_got chains. */
|
||||||
|
{
|
||||||
|
bfd *next;
|
||||||
|
|
||||||
|
bsub = a;
|
||||||
|
while ((next = alpha_elf_tdata (bsub)->in_got_link_next) != NULL)
|
||||||
|
bsub = next;
|
||||||
|
|
||||||
|
alpha_elf_tdata (bsub)->in_got_link_next = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
alpha_elf_tdata(a)->total_got_entries = total;
|
|
||||||
alpha_elf_tdata(b)->gotobj = a;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the offsets for the got entries. */
|
/* Calculate the offsets for the got entries. */
|
||||||
|
@ -2979,69 +3005,73 @@ elf64_alpha_size_got_sections (output_bfd, info)
|
||||||
bfd *output_bfd;
|
bfd *output_bfd;
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
{
|
{
|
||||||
bfd *i, *got_list, *cur_got_obj, **cur_got_tail;
|
bfd *i, *got_list, *cur_got_obj;
|
||||||
int ngots;
|
int something_changed = 0;
|
||||||
|
|
||||||
ngots = 0;
|
got_list = alpha_elf_hash_table (info)->got_list;
|
||||||
got_list = NULL;
|
|
||||||
cur_got_obj = NULL;
|
/* On the first time through, pretend we have an existing got list
|
||||||
cur_got_tail = NULL;
|
consisting of all of the input files. */
|
||||||
for (i = info->input_bfds; i ; i = i->link_next)
|
if (got_list == NULL)
|
||||||
{
|
{
|
||||||
bfd *this_got = alpha_elf_tdata (i)->gotobj;
|
for (i = info->input_bfds; i ; i = i->link_next)
|
||||||
|
|
||||||
/* Don't play if there is no .got for this input file. */
|
|
||||||
if (this_got == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES)
|
|
||||||
{
|
{
|
||||||
/* Yikes! A single object file has too many entries. */
|
bfd *this_got = alpha_elf_tdata (i)->gotobj;
|
||||||
(*_bfd_error_handler)
|
if (this_got == NULL)
|
||||||
(_("%s: .got subsegment exceeds 64K (size %d)"),
|
continue;
|
||||||
bfd_get_filename(i),
|
|
||||||
alpha_elf_tdata(this_got)->total_got_entries * 8);
|
/* We are assuming no merging has yet ocurred. */
|
||||||
return false;
|
BFD_ASSERT (this_got == i);
|
||||||
|
|
||||||
|
if (alpha_elf_tdata (this_got)->total_got_entries > MAX_GOT_ENTRIES)
|
||||||
|
{
|
||||||
|
/* Yikes! A single object file has too many entries. */
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%s: .got subsegment exceeds 64K (size %d)"),
|
||||||
|
bfd_get_filename (i),
|
||||||
|
alpha_elf_tdata (this_got)->total_got_entries * 8);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (got_list == NULL)
|
||||||
|
got_list = this_got;
|
||||||
|
else
|
||||||
|
alpha_elf_tdata(cur_got_obj)->got_link_next = this_got;
|
||||||
|
cur_got_obj = this_got;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_got_obj)
|
/* Strange degenerate case of no got references. */
|
||||||
|
if (got_list == NULL)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
alpha_elf_hash_table (info)->got_list = got_list;
|
||||||
|
|
||||||
|
/* Force got offsets to be recalculated. */
|
||||||
|
something_changed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur_got_obj = got_list;
|
||||||
|
i = alpha_elf_tdata(cur_got_obj)->got_link_next;
|
||||||
|
while (i != NULL)
|
||||||
|
{
|
||||||
|
if (elf64_alpha_can_merge_gots (cur_got_obj, i))
|
||||||
{
|
{
|
||||||
if (this_got == cur_got_obj)
|
elf64_alpha_merge_gots (cur_got_obj, i);
|
||||||
; /* Some previous pass merged us already. */
|
i = alpha_elf_tdata(i)->got_link_next;
|
||||||
else if (elf64_alpha_can_merge_gots (cur_got_obj, i))
|
alpha_elf_tdata(cur_got_obj)->got_link_next = i;
|
||||||
{
|
something_changed = 1;
|
||||||
elf64_alpha_merge_gots (cur_got_obj, i);
|
|
||||||
*cur_got_tail = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (++ngots == 2)
|
|
||||||
{
|
|
||||||
(*info->callbacks->warning)
|
|
||||||
(info, _("using multiple gp values"), (char *) NULL,
|
|
||||||
output_bfd, (asection *) NULL, (bfd_vma) 0);
|
|
||||||
}
|
|
||||||
*cur_got_tail = NULL;
|
|
||||||
alpha_elf_tdata(cur_got_obj)->got_link_next = got_list;
|
|
||||||
got_list = cur_got_obj;
|
|
||||||
cur_got_obj = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
++ngots;
|
|
||||||
cur_got_obj = i;
|
cur_got_obj = i;
|
||||||
|
i = alpha_elf_tdata(i)->got_link_next;
|
||||||
}
|
}
|
||||||
cur_got_tail = &alpha_elf_tdata(i)->in_got_link_next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_got_obj)
|
/* Once the gots have been merged, fill in the got offsets for
|
||||||
alpha_elf_tdata (cur_got_obj)->got_link_next = got_list;
|
everything therein. */
|
||||||
alpha_elf_hash_table (info)->got_list = cur_got_obj;
|
if (1 || something_changed)
|
||||||
|
elf64_alpha_calc_got_offsets (info);
|
||||||
/* Once the gots have been merged, fill in the got offsets for everything
|
|
||||||
therein. */
|
|
||||||
elf64_alpha_calc_got_offsets (info);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3108,39 +3138,31 @@ elf64_alpha_calc_dynrel_sizes (h, info)
|
||||||
|
|
||||||
/* If the symbol is dynamic, we'll need all the relocations in their
|
/* If the symbol is dynamic, we'll need all the relocations in their
|
||||||
natural form. If it has been forced local, we'll need the same
|
natural form. If it has been forced local, we'll need the same
|
||||||
number of RELATIVE relocations. */
|
number of RELATIVE relocations.
|
||||||
if (alpha_elf_dynamic_symbol_p (&h->root, info)
|
Except, don't add a .got reloc if we're not using a .plt entry. */
|
||||||
|| (info->shared && h->root.dynindx == -1))
|
|
||||||
|
if ((alpha_elf_dynamic_symbol_p (&h->root, info)
|
||||||
|
|| info->shared)
|
||||||
|
&& h->root.plt.offset == MINUS_ONE)
|
||||||
{
|
{
|
||||||
struct alpha_elf_reloc_entry *relent;
|
bfd *dynobj = elf_hash_table(info)->dynobj;
|
||||||
|
struct alpha_elf_got_entry *gotent;
|
||||||
|
bfd_size_type count = 0;
|
||||||
|
asection *srel;
|
||||||
|
|
||||||
for (relent = h->reloc_entries; relent; relent = relent->next)
|
for (gotent = h->got_entries; gotent ; gotent = gotent->next)
|
||||||
|
count++;
|
||||||
|
if (count > 0)
|
||||||
{
|
{
|
||||||
relent->srel->_raw_size +=
|
srel = bfd_get_section_by_name (dynobj, ".rela.got");
|
||||||
sizeof (Elf64_External_Rela) * relent->count;
|
BFD_ASSERT (srel != NULL);
|
||||||
}
|
srel->_raw_size += sizeof (Elf64_External_Rela) * count;
|
||||||
|
|
||||||
/* Only add a .rela.got entry if we're not using a .plt entry. */
|
|
||||||
if (h->root.plt_offset == MINUS_ONE)
|
|
||||||
{
|
|
||||||
bfd *dynobj = elf_hash_table(info)->dynobj;
|
|
||||||
struct alpha_elf_got_entry *gotent;
|
|
||||||
bfd_size_type count = 0;
|
|
||||||
asection *srel;
|
|
||||||
|
|
||||||
for (gotent = h->got_entries; gotent ; gotent = gotent->next)
|
|
||||||
count++;
|
|
||||||
if (count > 0)
|
|
||||||
{
|
|
||||||
srel = bfd_get_section_by_name (dynobj, ".rela.got");
|
|
||||||
BFD_ASSERT (srel != NULL);
|
|
||||||
srel->_raw_size += sizeof (Elf64_External_Rela) * count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Otherwise, shared objects require RELATIVE relocs for all REFQUAD
|
|
||||||
|
/* Shared objects require at least RELATIVE relocs for all REFQUAD
|
||||||
and REFLONG relocations. */
|
and REFLONG relocations. */
|
||||||
else if (info->shared)
|
if (info->shared)
|
||||||
{
|
{
|
||||||
struct alpha_elf_reloc_entry *relent;
|
struct alpha_elf_reloc_entry *relent;
|
||||||
|
|
||||||
|
@ -3581,7 +3603,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||||
/* If the symbol has been forced local, output a
|
/* If the symbol has been forced local, output a
|
||||||
RELATIVE reloc, otherwise it will be handled in
|
RELATIVE reloc, otherwise it will be handled in
|
||||||
finish_dynamic_symbol. */
|
finish_dynamic_symbol. */
|
||||||
if (info->shared && h->root.dynindx == -1)
|
if (info->shared
|
||||||
|
&& !alpha_elf_dynamic_symbol_p (&h->root, info))
|
||||||
{
|
{
|
||||||
Elf_Internal_Rela outrel;
|
Elf_Internal_Rela outrel;
|
||||||
|
|
||||||
|
@ -3794,7 +3817,7 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||||
{
|
{
|
||||||
bfd *dynobj = elf_hash_table(info)->dynobj;
|
bfd *dynobj = elf_hash_table(info)->dynobj;
|
||||||
|
|
||||||
if (h->plt_offset != MINUS_ONE)
|
if (h->plt.offset != MINUS_ONE)
|
||||||
{
|
{
|
||||||
/* Fill in the .plt entry for this symbol. */
|
/* Fill in the .plt entry for this symbol. */
|
||||||
asection *splt, *sgot, *srel;
|
asection *splt, *sgot, *srel;
|
||||||
|
@ -3822,21 +3845,21 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
|
||||||
+ gotent->got_offset);
|
+ gotent->got_offset);
|
||||||
plt_addr = (splt->output_section->vma
|
plt_addr = (splt->output_section->vma
|
||||||
+ splt->output_offset
|
+ splt->output_offset
|
||||||
+ h->plt_offset);
|
+ h->plt.offset);
|
||||||
|
|
||||||
plt_index = (h->plt_offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
|
plt_index = (h->plt.offset - PLT_HEADER_SIZE) / PLT_ENTRY_SIZE;
|
||||||
|
|
||||||
/* Fill in the entry in the procedure linkage table. */
|
/* Fill in the entry in the procedure linkage table. */
|
||||||
{
|
{
|
||||||
unsigned insn1, insn2, insn3;
|
unsigned insn1, insn2, insn3;
|
||||||
|
|
||||||
insn1 = PLT_ENTRY_WORD1 | ((-(h->plt_offset + 4) >> 2) & 0x1fffff);
|
insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
|
||||||
insn2 = PLT_ENTRY_WORD2;
|
insn2 = PLT_ENTRY_WORD2;
|
||||||
insn3 = PLT_ENTRY_WORD3;
|
insn3 = PLT_ENTRY_WORD3;
|
||||||
|
|
||||||
bfd_put_32 (output_bfd, insn1, splt->contents + h->plt_offset);
|
bfd_put_32 (output_bfd, insn1, splt->contents + h->plt.offset);
|
||||||
bfd_put_32 (output_bfd, insn2, splt->contents + h->plt_offset + 4);
|
bfd_put_32 (output_bfd, insn2, splt->contents + h->plt.offset + 4);
|
||||||
bfd_put_32 (output_bfd, insn3, splt->contents + h->plt_offset + 8);
|
bfd_put_32 (output_bfd, insn3, splt->contents + h->plt.offset + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in the entry in the .rela.plt section. */
|
/* Fill in the entry in the .rela.plt section. */
|
||||||
|
@ -4053,6 +4076,15 @@ elf64_alpha_final_link (abfd, info)
|
||||||
HDRR *symhdr = &debug.symbolic_header;
|
HDRR *symhdr = &debug.symbolic_header;
|
||||||
PTR mdebug_handle = NULL;
|
PTR mdebug_handle = NULL;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (++ngots == 2)
|
||||||
|
{
|
||||||
|
(*info->callbacks->warning)
|
||||||
|
(info, _("using multiple gp values"), (char *) NULL,
|
||||||
|
output_bfd, (asection *) NULL, (bfd_vma) 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Go through the sections and collect the .reginfo and .mdebug
|
/* Go through the sections and collect the .reginfo and .mdebug
|
||||||
information. */
|
information. */
|
||||||
reginfo_sec = NULL;
|
reginfo_sec = NULL;
|
||||||
|
@ -4764,5 +4796,7 @@ elf64_alpha_ecoff_debug_swap =
|
||||||
#define elf_backend_want_got_plt 0
|
#define elf_backend_want_got_plt 0
|
||||||
#define elf_backend_plt_readonly 0
|
#define elf_backend_plt_readonly 0
|
||||||
#define elf_backend_want_plt_sym 1
|
#define elf_backend_want_plt_sym 1
|
||||||
|
#define elf_backend_got_header_size 0
|
||||||
|
#define elf_backend_plt_header_size PLT_HEADER_SIZE
|
||||||
|
|
||||||
#include "elf64-target.h"
|
#include "elf64-target.h"
|
||||||
|
|
Loading…
Add table
Reference in a new issue