* elf64-alpha.c (struct alpha_relax_info): Add tsec & elfsym members.
(elf64_alpha_relax_section): Fill them in. (elf64_alpha_relax_opt_call): Implement more than a stub. (elf64_alpha_add_symbol_hook): Don't set SEC_LOAD or default alignment on .scommon. (elf64_alpha_merge_gots): Merge use counts as well.
This commit is contained in:
parent
986c3691f2
commit
2506b5688c
|
@ -1,3 +1,12 @@
|
||||||
|
Sat Apr 25 18:29:07 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
|
* elf64-alpha.c (struct alpha_relax_info): Add tsec & elfsym members.
|
||||||
|
(elf64_alpha_relax_section): Fill them in.
|
||||||
|
(elf64_alpha_relax_opt_call): Implement more than a stub.
|
||||||
|
(elf64_alpha_add_symbol_hook): Don't set SEC_LOAD or default
|
||||||
|
alignment on .scommon.
|
||||||
|
(elf64_alpha_merge_gots): Merge use counts as well.
|
||||||
|
|
||||||
Sat Apr 25 14:07:29 1998 Richard Henderson <rth@cygnus.com>
|
Sat Apr 25 14:07:29 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
* elf64-alpha.c (elf64_alpha_relax_section): Use the proper section
|
* elf64-alpha.c (elf64_alpha_relax_section): Use the proper section
|
||||||
|
|
|
@ -1042,6 +1042,8 @@ struct alpha_relax_info
|
||||||
boolean changed_relocs;
|
boolean changed_relocs;
|
||||||
bfd_vma gp;
|
bfd_vma gp;
|
||||||
bfd *gotobj;
|
bfd *gotobj;
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
@ -1209,7 +1211,13 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
|
||||||
urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
|
urel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
|
||||||
R_ALPHA_BRADDR);
|
R_ALPHA_BRADDR);
|
||||||
urel->r_addend = irel->r_addend;
|
urel->r_addend = irel->r_addend;
|
||||||
info->changed_relocs = true;
|
|
||||||
|
if (optdest)
|
||||||
|
urel->r_addend += optdest - symval;
|
||||||
|
else
|
||||||
|
all_optimized = false;
|
||||||
|
|
||||||
|
bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset);
|
||||||
|
|
||||||
/* Kill any HINT reloc that might exist for this insn. */
|
/* Kill any HINT reloc that might exist for this insn. */
|
||||||
xrel = (elf64_alpha_find_reloc_at_ofs
|
xrel = (elf64_alpha_find_reloc_at_ofs
|
||||||
|
@ -1218,13 +1226,8 @@ elf64_alpha_relax_with_lituse (info, symval, irel, irelend)
|
||||||
if (xrel)
|
if (xrel)
|
||||||
xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
|
xrel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
|
||||||
|
|
||||||
if (optdest)
|
|
||||||
urel->r_addend += optdest - symval;
|
|
||||||
else
|
|
||||||
all_optimized = false;
|
|
||||||
|
|
||||||
bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset);
|
|
||||||
info->changed_contents = true;
|
info->changed_contents = true;
|
||||||
|
info->changed_relocs = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
all_optimized = false;
|
all_optimized = false;
|
||||||
|
@ -1275,16 +1278,60 @@ elf64_alpha_relax_opt_call (info, symval)
|
||||||
{
|
{
|
||||||
/* If the function has the same gp, and we can identify that the
|
/* If the function has the same gp, and we can identify that the
|
||||||
function does not use its function pointer, we can eliminate the
|
function does not use its function pointer, we can eliminate the
|
||||||
address load.
|
address load. */
|
||||||
|
|
||||||
??? The .prologue [0,1] information is what we need. How do we
|
/* If the symbol is marked NOPV, we are being told the function never
|
||||||
get it out of the mdebug uglyness? What shall we do when we drop
|
needs its procedure value. */
|
||||||
that crap for dwarf2?
|
if (info->elfsym->st_other == STO_ALPHA_NOPV)
|
||||||
|
return symval;
|
||||||
|
|
||||||
For now, only consider the case in which there is an identifyable
|
/* If the symbol is marked STD_GP, we are being told the function does
|
||||||
GP load in the first two words. We can then skip over that load. */
|
a normal ldgp in the first two words. */
|
||||||
|
else if (info->elfsym->st_other == STO_ALPHA_STD_GPLOAD)
|
||||||
|
;
|
||||||
|
|
||||||
return 0;
|
/* Otherwise, we may be able to identify a GP load in the first two
|
||||||
|
words, which we can then skip. */
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Elf_Internal_Rela *tsec_relocs, *tsec_relend, *tsec_free, *gpdisp;
|
||||||
|
bfd_vma ofs;
|
||||||
|
|
||||||
|
/* Load the relocations from the section that the target symbol is in. */
|
||||||
|
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_free = (info->link_info->keep_memory ? NULL : tsec_relocs);
|
||||||
|
tsec_relend = tsec_relocs + info->tsec->reloc_count;
|
||||||
|
|
||||||
|
/* Recover the symbol's offset within the section. */
|
||||||
|
ofs = (symval - info->tsec->output_section->vma
|
||||||
|
- info->tsec->output_offset);
|
||||||
|
|
||||||
|
/* Look for a GPDISP reloc. */
|
||||||
|
gpdisp = (elf64_alpha_find_reloc_at_ofs
|
||||||
|
(tsec_relocs, tsec_relend, ofs, R_ALPHA_GPDISP));
|
||||||
|
|
||||||
|
if (!gpdisp || gpdisp->r_addend != 4)
|
||||||
|
{
|
||||||
|
if (tsec_free)
|
||||||
|
free (tsec_free);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (tsec_free)
|
||||||
|
free (tsec_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We've now determined that we can skip an initial gp load. Verify
|
||||||
|
that the call and the target use the same gp. */
|
||||||
|
if (info->link_info->hash->creator != info->tsec->owner->xvec
|
||||||
|
|| info->gotobj != alpha_elf_tdata (info->tsec->owner)->gotobj)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return symval + 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean
|
static boolean
|
||||||
|
@ -1417,6 +1464,7 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
{
|
{
|
||||||
bfd_vma symval;
|
bfd_vma symval;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
|
Elf_Internal_Sym isym;
|
||||||
|
|
||||||
if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL)
|
if (ELF64_R_TYPE (irel->r_info) != (int) R_ALPHA_LITERAL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1461,29 +1509,26 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
/* Get the value of the symbol referred to by the reloc. */
|
/* Get the value of the symbol referred to by the reloc. */
|
||||||
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
||||||
{
|
{
|
||||||
Elf_Internal_Sym isym;
|
|
||||||
asection *lsec;
|
|
||||||
|
|
||||||
/* A local symbol. */
|
/* A local symbol. */
|
||||||
bfd_elf64_swap_symbol_in (abfd,
|
bfd_elf64_swap_symbol_in (abfd,
|
||||||
extsyms + ELF64_R_SYM (irel->r_info),
|
extsyms + ELF64_R_SYM (irel->r_info),
|
||||||
&isym);
|
&isym);
|
||||||
if (isym.st_shndx == SHN_UNDEF)
|
if (isym.st_shndx == SHN_UNDEF)
|
||||||
lsec = bfd_und_section_ptr;
|
info.tsec = bfd_und_section_ptr;
|
||||||
else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
|
else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
|
||||||
lsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
|
info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
|
||||||
else if (isym.st_shndx == SHN_ABS)
|
else if (isym.st_shndx == SHN_ABS)
|
||||||
lsec = bfd_abs_section_ptr;
|
info.tsec = bfd_abs_section_ptr;
|
||||||
else if (isym.st_shndx == SHN_COMMON)
|
else if (isym.st_shndx == SHN_COMMON)
|
||||||
lsec = bfd_com_section_ptr;
|
info.tsec = bfd_com_section_ptr;
|
||||||
else
|
else
|
||||||
continue; /* who knows. */
|
continue; /* who knows. */
|
||||||
|
|
||||||
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)];
|
||||||
symval = (isym.st_value
|
info.elfsym = &isym;
|
||||||
+ lsec->output_section->vma
|
symval = isym.st_value;
|
||||||
+ lsec->output_offset);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1509,10 +1554,11 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
||||||
|
|
||||||
info.h = h;
|
info.h = h;
|
||||||
info.gotent = gotent;
|
info.gotent = gotent;
|
||||||
symval = (h->root.root.u.def.value
|
info.tsec = h->root.root.u.def.section;
|
||||||
+ h->root.root.u.def.section->output_section->vma
|
info.elfsym = &((elf_symbol_type *) h)->internal_elf_sym;
|
||||||
+ h->root.root.u.def.section->output_offset);
|
symval = h->root.root.u.def.value;
|
||||||
}
|
}
|
||||||
|
symval += info.tsec->output_section->vma + info.tsec->output_offset;
|
||||||
symval += irel->r_addend;
|
symval += irel->r_addend;
|
||||||
|
|
||||||
BFD_ASSERT(info.gotent != NULL);
|
BFD_ASSERT(info.gotent != NULL);
|
||||||
|
@ -1749,18 +1795,12 @@ elf64_alpha_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
|
||||||
{
|
{
|
||||||
scomm = bfd_make_section (abfd, ".scommon");
|
scomm = bfd_make_section (abfd, ".scommon");
|
||||||
if (scomm == NULL
|
if (scomm == NULL
|
||||||
|| !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC | SEC_LOAD
|
|| !bfd_set_section_flags (abfd, scomm, (SEC_ALLOC
|
||||||
| SEC_IS_COMMON
|
| SEC_IS_COMMON
|
||||||
| SEC_LINKER_CREATED)))
|
| SEC_LINKER_CREATED)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bfd_get_section_alignment (abfd, scomm) < sym->st_value)
|
|
||||||
{
|
|
||||||
if (!bfd_set_section_alignment (abfd, scomm, sym->st_value))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
*secp = scomm;
|
*secp = scomm;
|
||||||
*valp = sym->st_size;
|
*valp = sym->st_size;
|
||||||
}
|
}
|
||||||
|
@ -2833,6 +2873,7 @@ elf64_alpha_merge_gots (a, b)
|
||||||
if (ae->gotobj == a && ae->addend == be->addend)
|
if (ae->gotobj == a && ae->addend == be->addend)
|
||||||
{
|
{
|
||||||
ae->flags |= be->flags;
|
ae->flags |= be->flags;
|
||||||
|
ae->use_count += be->use_count;
|
||||||
*pbe = be->next;
|
*pbe = be->next;
|
||||||
goto global_found;
|
goto global_found;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue