* bfd/elf64-alpha.c (elf64_alpha_relocate_section): Use the

got_enties of the default symbol for the default versioned
        symbol.  Patch from hjl@gnu.ai.mit.edu, modified not to use
        alloca in the loop.
This commit is contained in:
Richard Henderson
1997-10-14 04:24:59 +00:00
parent d5cecca93c
commit 3a13dd8f03
2 changed files with 242 additions and 31 deletions

View File

@ -1,3 +1,10 @@
Mon Oct 13 21:24:04 1997 Richard Henderson <rth@cygnus.com>
* bfd/elf64-alpha.c (elf64_alpha_relocate_section): Use the
got_enties of the default symbol for the default versioned
symbol. Patch from hjl@gnu.ai.mit.edu, modified not to use
alloca in the loop.
Mon Oct 13 17:37:37 1997 Nick Clifton <nickc@cygnus.com> Mon Oct 13 17:37:37 1997 Nick Clifton <nickc@cygnus.com>
* elf32-v850.c (v850_elf_final_link_relocate): Only use the bottom * elf32-v850.c (v850_elf_final_link_relocate): Only use the bottom

View File

@ -329,6 +329,22 @@ elf64_alpha_mkobject (abfd)
return false; return false;
return true; return true;
} }
static boolean
elf64_alpha_object_p (abfd)
bfd *abfd;
{
/* Allocate our special target data. */
struct alpha_elf_obj_tdata *new_tdata;
new_tdata = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata));
if (new_tdata == NULL)
return false;
new_tdata->root = *abfd->tdata.elf_obj_data;
abfd->tdata.any = new_tdata;
/* Set the right machine number for an Alpha ELF file. */
return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
}
/* In case we're on a 32-bit machine, construct a 64-bit "-1" value /* In case we're on a 32-bit machine, construct a 64-bit "-1" value
from smaller values. Start with zero, widen, *then* decrement. */ from smaller values. Start with zero, widen, *then* decrement. */
@ -539,7 +555,8 @@ static reloc_howto_type elf64_alpha_howto_table[] =
false), /* pcrel_offset */ false), /* pcrel_offset */
/* Push a value on the reloc evaluation stack. */ /* Push a value on the reloc evaluation stack. */
HOWTO (ALPHA_R_OP_PUSH, /* type */ /* Not implemented -- it's dumb. */
HOWTO (R_ALPHA_OP_PUSH, /* type */
0, /* rightshift */ 0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */ 0, /* bitsize */
@ -555,7 +572,8 @@ static reloc_howto_type elf64_alpha_howto_table[] =
/* Store the value from the stack at the given address. Store it in /* Store the value from the stack at the given address. Store it in
a bitfield of size r_size starting at bit position r_offset. */ a bitfield of size r_size starting at bit position r_offset. */
HOWTO (ALPHA_R_OP_STORE, /* type */ /* Not implemented -- it's dumb. */
HOWTO (R_ALPHA_OP_STORE, /* type */
0, /* rightshift */ 0, /* rightshift */
4, /* size (0 = byte, 1 = short, 2 = long) */ 4, /* size (0 = byte, 1 = short, 2 = long) */
64, /* bitsize */ 64, /* bitsize */
@ -571,7 +589,8 @@ static reloc_howto_type elf64_alpha_howto_table[] =
/* Subtract the reloc address from the value on the top of the /* Subtract the reloc address from the value on the top of the
relocation stack. */ relocation stack. */
HOWTO (ALPHA_R_OP_PSUB, /* type */ /* Not implemented -- it's dumb. */
HOWTO (R_ALPHA_OP_PSUB, /* type */
0, /* rightshift */ 0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */ 0, /* bitsize */
@ -587,7 +606,8 @@ static reloc_howto_type elf64_alpha_howto_table[] =
/* Shift the value on the top of the relocation stack right by the /* Shift the value on the top of the relocation stack right by the
given value. */ given value. */
HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ /* Not implemented -- it's dumb. */
HOWTO (R_ALPHA_OP_PRSHIFT, /* type */
0, /* rightshift */ 0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */ 0, /* bitsize */
@ -601,7 +621,146 @@ static reloc_howto_type elf64_alpha_howto_table[] =
0, /* dst_mask */ 0, /* dst_mask */
false), /* pcrel_offset */ false), /* pcrel_offset */
/* Change the value of GP used by +r_addend until the next GPVALUE or the
end of the input bfd. */
/* Not implemented -- it's dumb. */
HOWTO (R_ALPHA_GPVALUE,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"GPVALUE", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The high 16 bits of the displacement from GP to the target. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_GPRELHIGH,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"GPRELHIGH", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The low 16 bits of the displacement from GP to the target. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_GPRELLOW,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"GPRELLOW", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* A 16-bit displacement from the GP to the target. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_IMMED_GP_16,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"IMMED_GP_16", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The high bits of a 32-bit displacement from the GP to the target; the
low bits are supplied in the subsequent R_ALPHA_IMMED_LO32 relocs. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_IMMED_GP_HI32,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"IMMED_GP_HI32", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The high bits of a 32-bit displacement to the starting address of the
current section (the relocation target is ignored); the low bits are
supplied in the subsequent R_ALPHA_IMMED_LO32 relocs. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_IMMED_SCN_HI32,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"IMMED_SCN_HI32", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The high bits of a 32-bit displacement from the previous br, bsr, jsr
or jmp insn (as tagged by a BRADDR or HINT reloc) to the target; the
low bits are supplied by subsequent R_ALPHA_IMMED_LO32 relocs. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_IMMED_BR_HI32,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"IMMED_BR_HI32", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* The low 16 bits of a displacement calculated in a previous HI32 reloc. */
/* XXX: Not implemented. */
HOWTO (R_ALPHA_IMMED_LO32,
0, /* rightshift */
0, /* size (0 = byte, 1 = short, 2 = long) */
0, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_dont, /* complain_on_overflow */
elf64_alpha_reloc_bad, /* special_function */
"IMMED_LO32", /* name */
false, /* partial_inplace */
0, /* src_mask */
0, /* dst_mask */
false), /* pcrel_offset */
/* Misc ELF relocations. */ /* Misc ELF relocations. */
/* A dynamic relocation to copy the target into our .dynbss section. */
/* Not generated, as all Alpha objects use PIC, so it is not needed. It
is present because every other ELF has one, but should not be used
because .dynbss is an ugly thing. */
HOWTO (R_ALPHA_COPY, HOWTO (R_ALPHA_COPY,
0, 0,
0, 0,
@ -616,6 +775,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
0, 0,
true), true),
/* A dynamic relocation for a .got entry. */
HOWTO (R_ALPHA_GLOB_DAT, HOWTO (R_ALPHA_GLOB_DAT,
0, 0,
0, 0,
@ -630,6 +790,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
0, 0,
true), true),
/* A dynamic relocation for a .plt entry. */
HOWTO (R_ALPHA_JMP_SLOT, HOWTO (R_ALPHA_JMP_SLOT,
0, 0,
0, 0,
@ -644,6 +805,7 @@ static reloc_howto_type elf64_alpha_howto_table[] =
0, 0,
true), true),
/* A dynamic relocation to add the base of the DSO to a 64-bit field. */
HOWTO (R_ALPHA_RELATIVE, HOWTO (R_ALPHA_RELATIVE,
0, 0,
0, 0,
@ -850,23 +1012,14 @@ elf64_alpha_info_to_howto (abfd, cache_ptr, dst)
#define PLT_HEADER_WORD4 0x6b7b0000 /* jmp $27,($27) */ #define PLT_HEADER_WORD4 0x6b7b0000 /* jmp $27,($27) */
#define PLT_ENTRY_SIZE 12 #define PLT_ENTRY_SIZE 12
#define PLT_ENTRY_WORD1 0x279f0000 /* ldah $28, 0($31) */ #define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */
#define PLT_ENTRY_WORD2 0x239c0000 /* lda $28, 0($28) */ #define PLT_ENTRY_WORD2 0
#define PLT_ENTRY_WORD3 0xc3e00000 /* br $31, plt0 */ #define PLT_ENTRY_WORD3 0
#define MAX_GOT_ENTRIES (64*1024 / 8) #define MAX_GOT_ENTRIES (64*1024 / 8)
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so" #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so"
/* Set the right machine number for an Alpha ELF file. */
static boolean
elf64_alpha_object_p (abfd)
bfd *abfd;
{
return bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0);
}
/* Handle an Alpha specific section when reading an object file. This /* Handle an Alpha specific section when reading an object file. This
is called when elfcode.h finds a section with an unknown type. is called when elfcode.h finds a section with an unknown type.
FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure FIXME: We need to handle the SHF_MIPS_GPREL flag, but I'm not sure
@ -1785,7 +1938,8 @@ elf64_alpha_adjust_dynamic_symbol (info, h)
if (h->root.type != bfd_link_hash_undefweak if (h->root.type != bfd_link_hash_undefweak
&& alpha_elf_dynamic_symbol_p (h, info) && alpha_elf_dynamic_symbol_p (h, info)
&& (h->type == STT_FUNC && ((h->type == STT_FUNC
&& !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
|| (h->type == STT_NOTYPE || (h->type == STT_NOTYPE
&& ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC)) && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC))
/* Don't prevent otherwise valid programs from linking by attempting /* Don't prevent otherwise valid programs from linking by attempting
@ -1946,6 +2100,7 @@ elf64_alpha_merge_gots (a, b)
for (ae = *start; ae ; ae = ae->next) for (ae = *start; ae ; ae = ae->next)
if (ae->gotobj == a && ae->addend == be->addend) if (ae->gotobj == a && ae->addend == be->addend)
{ {
ae->flags |= be->flags;
*pbe = be->next; *pbe = be->next;
goto global_found; goto global_found;
} }
@ -2297,7 +2452,8 @@ elf64_alpha_size_dynamic_sections (output_bfd, info)
s->output_section); s->output_section);
target = bfd_get_section_by_name (output_bfd, outname + 5); target = bfd_get_section_by_name (output_bfd, outname + 5);
if (target != NULL if (target != NULL
&& (target->flags & SEC_READONLY) != 0) && (target->flags & SEC_READONLY) != 0
&& (target->flags & SEC_ALLOC) != 0)
reltext = true; reltext = true;
if (strcmp(name, ".rela.plt") == 0) if (strcmp(name, ".rela.plt") == 0)
@ -2610,6 +2766,39 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
if (h != NULL) if (h != NULL)
{ {
gotent = h->got_entries; gotent = h->got_entries;
/* We may be looking at a default versioned symbol, which
won't have the got entries we set up earlier. Go find
the original. */
if (!gotent)
{
struct alpha_elf_link_hash_entry *v;
char *p, *name;
size_t len;
p = strchr (h->root.root.root.string, ELF_VER_CHR);
BFD_ASSERT (p != NULL && p[1] == ELF_VER_CHR);
len = p - h->root.root.root.string;
name = bfd_malloc (len + 1);
if (name == NULL)
return false;
memcpy (name, h->root.root.root.string, len);
name[len] = '\0';
v = alpha_elf_link_hash_lookup (alpha_elf_hash_table (info),
name, false, false, false);
BFD_ASSERT (v != NULL);
while (v->got_entries == NULL)
{
BFD_ASSERT (v->root.root.type==bfd_link_hash_indirect);
v = (struct alpha_elf_link_hash_entry *)
v->root.root.u.i.link;
}
gotent = v->got_entries;
free (name);
}
while (gotent->gotobj != gotobj || gotent->addend != addend) while (gotent->gotobj != gotobj || gotent->addend != addend)
gotent = gotent->next; gotent = gotent->next;
@ -2687,6 +2876,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
case R_ALPHA_REFQUAD: case R_ALPHA_REFQUAD:
{ {
Elf_Internal_Rela outrel; Elf_Internal_Rela outrel;
boolean skip;
/* Careful here to remember RELATIVE relocations for global /* Careful here to remember RELATIVE relocations for global
variables for symbolic shared objects. */ variables for symbolic shared objects. */
@ -2719,9 +2909,29 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section,
BFD_ASSERT(srel != NULL); BFD_ASSERT(srel != NULL);
} }
outrel.r_offset = (input_section->output_section->vma skip = false;
+ input_section->output_offset
+ rel->r_offset); if (elf_section_data (input_section)->stab_info == NULL)
outrel.r_offset = rel->r_offset;
else
{
bfd_vma off;
off = (_bfd_stab_section_offset
(output_bfd, &elf_hash_table (info)->stab_info,
input_section,
&elf_section_data (input_section)->stab_info,
rel->r_offset));
if (off == (bfd_vma) -1)
skip = true;
outrel.r_offset = off;
}
if (! skip)
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
else
memset (&outrel, 0, sizeof outrel);
bfd_elf64_swap_reloca_out (output_bfd, &outrel, bfd_elf64_swap_reloca_out (output_bfd, &outrel,
((Elf64_External_Rela *) ((Elf64_External_Rela *)
@ -2821,16 +3031,10 @@ elf64_alpha_finish_dynamic_symbol (output_bfd, info, h, sym)
/* 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;
long hi, lo;
/* decompose the reloc offset for the plt for ldah+lda */ insn1 = PLT_ENTRY_WORD1 | ((-(h->plt_offset + 4) >> 2) & 0x1fffff);
hi = plt_index * sizeof(Elf64_External_Rela); insn2 = PLT_ENTRY_WORD2;
lo = ((hi & 0xffff) ^ 0x8000) - 0x8000; insn3 = PLT_ENTRY_WORD3;
hi = (hi - lo) >> 16;
insn1 = PLT_ENTRY_WORD1 | (hi & 0xffff);
insn2 = PLT_ENTRY_WORD2 | (lo & 0xffff);
insn3 = PLT_ENTRY_WORD3 | ((-(h->plt_offset + 12) >> 2) & 0x1fffff);
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);
@ -3715,9 +3919,9 @@ elf64_alpha_ecoff_debug_swap =
#define bfd_elf64_mkobject \ #define bfd_elf64_mkobject \
elf64_alpha_mkobject elf64_alpha_mkobject
#define elf_backend_object_p \ #define elf_backend_object_p \
elf64_alpha_object_p elf64_alpha_object_p
#define elf_backend_section_from_shdr \ #define elf_backend_section_from_shdr \
elf64_alpha_section_from_shdr elf64_alpha_section_from_shdr
#define elf_backend_fake_sections \ #define elf_backend_fake_sections \