mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-28 15:18:37 +08:00
* elf64-alpha.c (elf64_alpha_relax_with_lituse): Relax jsr to
undefweak to use zero register. Call elf64_alpha_relax_got_load if not all uses removed. (elf64_alpha_relax_got_load): Relax undefweak to lda zero. (elf64_alpha_relax_section): Handle undefweak symbols. (elf64_alpha_calc_dynrel_sizes): Don't add relocs for undefweak. (elf64_alpha_size_rela_got_1): Likewise. (elf64_alpha_relocate_section): Likewise.
This commit is contained in:
@ -1,3 +1,14 @@
|
|||||||
|
2005-05-22 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
|
* elf64-alpha.c (elf64_alpha_relax_with_lituse): Relax jsr to
|
||||||
|
undefweak to use zero register. Call elf64_alpha_relax_got_load
|
||||||
|
if not all uses removed.
|
||||||
|
(elf64_alpha_relax_got_load): Relax undefweak to lda zero.
|
||||||
|
(elf64_alpha_relax_section): Handle undefweak symbols.
|
||||||
|
(elf64_alpha_calc_dynrel_sizes): Don't add relocs for undefweak.
|
||||||
|
(elf64_alpha_size_rela_got_1): Likewise.
|
||||||
|
(elf64_alpha_relocate_section): Likewise.
|
||||||
|
|
||||||
2005-05-22 Richard Henderson <rth@redhat.com>
|
2005-05-22 Richard Henderson <rth@redhat.com>
|
||||||
|
|
||||||
* elf64-alpha.c (elf64_alpha_relax_section): Only operate
|
* elf64-alpha.c (elf64_alpha_relax_section): Only operate
|
||||||
|
@ -1300,9 +1300,7 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
|
|||||||
/* Extract the displacement from the instruction, sign-extending
|
/* Extract the displacement from the instruction, sign-extending
|
||||||
it if necessary, then test whether it is within 16 or 32 bits
|
it if necessary, then test whether it is within 16 or 32 bits
|
||||||
displacement from GP. */
|
displacement from GP. */
|
||||||
insn_disp = insn & 0x0000ffff;
|
insn_disp = ((insn & 0xffff) ^ 0x8000) - 0x8000;
|
||||||
if (insn_disp & 0x8000)
|
|
||||||
insn_disp |= ~0xffff; /* Negative: sign-extend. */
|
|
||||||
|
|
||||||
xdisp = disp + insn_disp;
|
xdisp = disp + insn_disp;
|
||||||
fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
|
fits16 = (xdisp >= - (bfd_signed_vma) 0x8000 && xdisp < 0x8000);
|
||||||
@ -1371,6 +1369,19 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
|
|||||||
bfd_vma optdest, org;
|
bfd_vma optdest, org;
|
||||||
bfd_signed_vma odisp;
|
bfd_signed_vma odisp;
|
||||||
|
|
||||||
|
/* For undefined weak symbols, we're mostly interested in getting
|
||||||
|
rid of the got entry whenever possible, so optimize this to a
|
||||||
|
use of the zero register. */
|
||||||
|
if (info->h && info->h->root.root.type == bfd_link_hash_undefweak)
|
||||||
|
{
|
||||||
|
insn |= 31 << 16;
|
||||||
|
bfd_put_32 (info->abfd, (bfd_vma) insn,
|
||||||
|
info->contents + urel->r_offset);
|
||||||
|
|
||||||
|
info->changed_contents = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* If not zero, place to jump without needing pv. */
|
/* If not zero, place to jump without needing pv. */
|
||||||
optdest = elf64_alpha_relax_opt_call (info, symval);
|
optdest = elf64_alpha_relax_opt_call (info, symval);
|
||||||
org = (info->sec->output_section->vma
|
org = (info->sec->output_section->vma
|
||||||
@ -1474,9 +1485,11 @@ elf64_alpha_relax_with_lituse (info, symval, irel)
|
|||||||
info->contents + irel->r_offset);
|
info->contents + irel->r_offset);
|
||||||
info->changed_contents = TRUE;
|
info->changed_contents = TRUE;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return elf64_alpha_relax_got_load (info, symval, irel, R_ALPHA_LITERAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bfd_vma
|
static bfd_vma
|
||||||
@ -1583,7 +1596,25 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
if (r_type == R_ALPHA_LITERAL)
|
if (r_type == R_ALPHA_LITERAL)
|
||||||
|
{
|
||||||
|
/* Look for nice constant addresses. This includes the not-uncommon
|
||||||
|
special case of 0 for undefweak symbols. */
|
||||||
|
if ((info->h && info->h->root.root.type == bfd_link_hash_undefweak)
|
||||||
|
|| (!info->link_info->shared
|
||||||
|
&& (symval >= (bfd_vma)-0x8000 || symval < 0x8000)))
|
||||||
|
{
|
||||||
|
disp = 0;
|
||||||
|
insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
|
||||||
|
insn |= (symval & 0xffff);
|
||||||
|
r_type = R_ALPHA_NONE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
disp = symval - info->gp;
|
disp = symval - info->gp;
|
||||||
|
insn = (OP_LDA << 26) | (insn & 0x03ff0000);
|
||||||
|
r_type = R_ALPHA_GPREL16;
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_vma dtp_base, tp_base;
|
bfd_vma dtp_base, tp_base;
|
||||||
@ -1592,17 +1623,26 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
|
|||||||
dtp_base = alpha_get_dtprel_base (info->link_info);
|
dtp_base = alpha_get_dtprel_base (info->link_info);
|
||||||
tp_base = alpha_get_tprel_base (info->link_info);
|
tp_base = alpha_get_tprel_base (info->link_info);
|
||||||
disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
|
disp = symval - (r_type == R_ALPHA_GOTDTPREL ? dtp_base : tp_base);
|
||||||
|
|
||||||
|
insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
|
||||||
|
|
||||||
|
switch (r_type)
|
||||||
|
{
|
||||||
|
case R_ALPHA_GOTDTPREL:
|
||||||
|
r_type = R_ALPHA_DTPREL16;
|
||||||
|
break;
|
||||||
|
case R_ALPHA_GOTTPREL:
|
||||||
|
r_type = R_ALPHA_TPREL16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BFD_ASSERT (0);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disp < -0x8000 || disp >= 0x8000)
|
if (disp < -0x8000 || disp >= 0x8000)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Exchange LDQ for LDA. In the case of the TLS relocs, we're loading
|
|
||||||
a constant, so force the base register to be $31. */
|
|
||||||
if (r_type == R_ALPHA_LITERAL)
|
|
||||||
insn = (OP_LDA << 26) | (insn & 0x03ff0000);
|
|
||||||
else
|
|
||||||
insn = (OP_LDA << 26) | (insn & (31 << 21)) | (31 << 16);
|
|
||||||
bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
|
bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
|
||||||
info->changed_contents = TRUE;
|
info->changed_contents = TRUE;
|
||||||
|
|
||||||
@ -1617,22 +1657,6 @@ elf64_alpha_relax_got_load (info, symval, irel, r_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Smash the existing GOT relocation for its 16-bit immediate pair. */
|
/* Smash the existing GOT relocation for its 16-bit immediate pair. */
|
||||||
switch (r_type)
|
|
||||||
{
|
|
||||||
case R_ALPHA_LITERAL:
|
|
||||||
r_type = R_ALPHA_GPREL16;
|
|
||||||
break;
|
|
||||||
case R_ALPHA_GOTDTPREL:
|
|
||||||
r_type = R_ALPHA_DTPREL16;
|
|
||||||
break;
|
|
||||||
case R_ALPHA_GOTTPREL:
|
|
||||||
r_type = R_ALPHA_TPREL16;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
BFD_ASSERT (0);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
|
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), r_type);
|
||||||
info->changed_relocs = TRUE;
|
info->changed_relocs = TRUE;
|
||||||
|
|
||||||
@ -2103,13 +2127,17 @@ elf64_alpha_relax_section (abfd, sec, link_info, again)
|
|||||||
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;
|
||||||
|
|
||||||
/* If the symbol is undefined, we can't do anything with it. */
|
/* If the symbol is undefined, we can't do anything with it. */
|
||||||
if (h->root.root.type == bfd_link_hash_undefweak
|
if (h->root.root.type == bfd_link_hash_undefined)
|
||||||
|| h->root.root.type == bfd_link_hash_undefined)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If the symbol isn't defined in the current module, again
|
/* If the symbol isn't defined in the current module,
|
||||||
we can't do anything. */
|
again we can't do anything. */
|
||||||
if (!h->root.def_regular)
|
if (h->root.root.type == bfd_link_hash_undefweak)
|
||||||
|
{
|
||||||
|
info.tsec = bfd_abs_section_ptr;
|
||||||
|
symval = 0;
|
||||||
|
}
|
||||||
|
else if (!h->root.def_regular)
|
||||||
{
|
{
|
||||||
/* Except for TLSGD relocs, which can sometimes be
|
/* Except for TLSGD relocs, which can sometimes be
|
||||||
relaxed to GOTTPREL relocs. */
|
relaxed to GOTTPREL relocs. */
|
||||||
@ -3860,9 +3888,14 @@ 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 this is a shared object, and it has been forced
|
natural form. If this is a shared object, and it has been forced
|
||||||
local, we'll need the same number of RELATIVE relocations. */
|
local, we'll need the same number of RELATIVE relocations. */
|
||||||
|
|
||||||
dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
|
dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
|
||||||
|
|
||||||
|
/* If the symbol is a hidden undefined weak, then we never have any
|
||||||
|
relocations. Avoid the loop which may want to add RELATIVE relocs
|
||||||
|
based on info->shared. */
|
||||||
|
if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
for (relent = h->reloc_entries; relent; relent = relent->next)
|
for (relent = h->reloc_entries; relent; relent = relent->next)
|
||||||
{
|
{
|
||||||
entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
|
entries = alpha_dynamic_entries_for_reloc (relent->rtype, dynamic,
|
||||||
@ -3950,9 +3983,14 @@ elf64_alpha_size_rela_got_1 (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 this is a shared object, and it has been forced
|
natural form. If this is a shared object, and it has been forced
|
||||||
local, we'll need the same number of RELATIVE relocations. */
|
local, we'll need the same number of RELATIVE relocations. */
|
||||||
|
|
||||||
dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
|
dynamic = alpha_elf_dynamic_symbol_p (&h->root, info);
|
||||||
|
|
||||||
|
/* If the symbol is a hidden undefined weak, then we never have any
|
||||||
|
relocations. Avoid the loop which may want to add RELATIVE relocs
|
||||||
|
based on info->shared. */
|
||||||
|
if (h->root.root.type == bfd_link_hash_undefweak && !dynamic)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
entries = 0;
|
entries = 0;
|
||||||
for (gotent = h->got_entries; gotent ; gotent = gotent->next)
|
for (gotent = h->got_entries; gotent ; gotent = gotent->next)
|
||||||
if (gotent->use_count > 0)
|
if (gotent->use_count > 0)
|
||||||
@ -4445,7 +4483,7 @@ 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 && !dynamic_symbol_p)
|
if (info->shared && !dynamic_symbol_p && !undef_weak_ref)
|
||||||
elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
|
elf64_alpha_emit_dynrel (output_bfd, info, sgot, srelgot,
|
||||||
gotent->got_offset, 0,
|
gotent->got_offset, 0,
|
||||||
R_ALPHA_RELATIVE, value);
|
R_ALPHA_RELATIVE, value);
|
||||||
@ -4617,7 +4655,8 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
}
|
}
|
||||||
else if (info->shared
|
else if (info->shared
|
||||||
&& r_symndx != 0
|
&& r_symndx != 0
|
||||||
&& (input_section->flags & SEC_ALLOC))
|
&& (input_section->flags & SEC_ALLOC)
|
||||||
|
&& !undef_weak_ref)
|
||||||
{
|
{
|
||||||
if (r_type == R_ALPHA_REFLONG)
|
if (r_type == R_ALPHA_REFLONG)
|
||||||
{
|
{
|
||||||
@ -4650,6 +4689,14 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
|
|||||||
input_bfd, h->root.root.root.string);
|
input_bfd, h->root.root.root.string);
|
||||||
ret_val = FALSE;
|
ret_val = FALSE;
|
||||||
}
|
}
|
||||||
|
else if ((info->shared || info->pie) && undef_weak_ref)
|
||||||
|
{
|
||||||
|
(*_bfd_error_handler)
|
||||||
|
(_("%B: pc-relative relocation against undefined weak symbol %s"),
|
||||||
|
input_bfd, h->root.root.root.string);
|
||||||
|
ret_val = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ??? .eh_frame references to discarded sections will be smashed
|
/* ??? .eh_frame references to discarded sections will be smashed
|
||||||
to relocations against SHN_UNDEF. The .eh_frame format allows
|
to relocations against SHN_UNDEF. The .eh_frame format allows
|
||||||
|
Reference in New Issue
Block a user