diff options
author | Richard Henderson <rth@redhat.com> | 1997-10-14 04:24:59 +0000 |
---|---|---|
committer | Richard Henderson <rth@redhat.com> | 1997-10-14 04:24:59 +0000 |
commit | 3a13dd8f037041f91b4f68d451d51d19bf5ad295 (patch) | |
tree | c1cfcce76cdbadea36aa77752b5f21d03621ae2f | |
parent | d5cecca93cccbd347346d68d8bce8371b675a806 (diff) | |
download | gdb-3a13dd8f037041f91b4f68d451d51d19bf5ad295.zip gdb-3a13dd8f037041f91b4f68d451d51d19bf5ad295.tar.gz gdb-3a13dd8f037041f91b4f68d451d51d19bf5ad295.tar.bz2 |
* 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.
-rw-r--r-- | bfd/ChangeLog | 7 | ||||
-rw-r--r-- | bfd/elf64-alpha.c | 266 |
2 files changed, 242 insertions, 31 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7ea12a1..e225986 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -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> * elf32-v850.c (v850_elf_final_link_relocate): Only use the bottom diff --git a/bfd/elf64-alpha.c b/bfd/elf64-alpha.c index e61d5d0..3de8dca 100644 --- a/bfd/elf64-alpha.c +++ b/bfd/elf64-alpha.c @@ -329,6 +329,22 @@ elf64_alpha_mkobject (abfd) return false; 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 from smaller values. Start with zero, widen, *then* decrement. */ @@ -539,7 +555,8 @@ static reloc_howto_type elf64_alpha_howto_table[] = false), /* pcrel_offset */ /* 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, /* size (0 = byte, 1 = short, 2 = long) */ 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 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 */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 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 relocation stack. */ - HOWTO (ALPHA_R_OP_PSUB, /* type */ + /* Not implemented -- it's dumb. */ + HOWTO (R_ALPHA_OP_PSUB, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 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 given value. */ - HOWTO (ALPHA_R_OP_PRSHIFT, /* type */ + /* Not implemented -- it's dumb. */ + HOWTO (R_ALPHA_OP_PRSHIFT, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ @@ -601,7 +621,146 @@ static reloc_howto_type elf64_alpha_howto_table[] = 0, /* dst_mask */ 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. */ + + /* 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, 0, 0, @@ -616,6 +775,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = 0, true), + /* A dynamic relocation for a .got entry. */ HOWTO (R_ALPHA_GLOB_DAT, 0, 0, @@ -630,6 +790,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = 0, true), + /* A dynamic relocation for a .plt entry. */ HOWTO (R_ALPHA_JMP_SLOT, 0, 0, @@ -644,6 +805,7 @@ static reloc_howto_type elf64_alpha_howto_table[] = 0, true), + /* A dynamic relocation to add the base of the DSO to a 64-bit field. */ HOWTO (R_ALPHA_RELATIVE, 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_ENTRY_SIZE 12 -#define PLT_ENTRY_WORD1 0x279f0000 /* ldah $28, 0($31) */ -#define PLT_ENTRY_WORD2 0x239c0000 /* lda $28, 0($28) */ -#define PLT_ENTRY_WORD3 0xc3e00000 /* br $31, plt0 */ +#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */ +#define PLT_ENTRY_WORD2 0 +#define PLT_ENTRY_WORD3 0 #define MAX_GOT_ENTRIES (64*1024 / 8) #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 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 @@ -1785,7 +1938,8 @@ elf64_alpha_adjust_dynamic_symbol (info, h) if (h->root.type != bfd_link_hash_undefweak && 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 && ah->flags == ALPHA_ELF_LINK_HASH_LU_FUNC)) /* 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) if (ae->gotobj == a && ae->addend == be->addend) { + ae->flags |= be->flags; *pbe = be->next; goto global_found; } @@ -2297,7 +2452,8 @@ elf64_alpha_size_dynamic_sections (output_bfd, info) s->output_section); target = bfd_get_section_by_name (output_bfd, outname + 5); if (target != NULL - && (target->flags & SEC_READONLY) != 0) + && (target->flags & SEC_READONLY) != 0 + && (target->flags & SEC_ALLOC) != 0) reltext = true; if (strcmp(name, ".rela.plt") == 0) @@ -2610,6 +2766,39 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, if (h != NULL) { 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) gotent = gotent->next; @@ -2687,6 +2876,7 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, case R_ALPHA_REFQUAD: { Elf_Internal_Rela outrel; + boolean skip; /* Careful here to remember RELATIVE relocations for global variables for symbolic shared objects. */ @@ -2719,9 +2909,29 @@ elf64_alpha_relocate_section (output_bfd, info, input_bfd, input_section, BFD_ASSERT(srel != NULL); } - outrel.r_offset = (input_section->output_section->vma - + input_section->output_offset - + rel->r_offset); + skip = false; + + 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, ((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. */ { unsigned insn1, insn2, insn3; - long hi, lo; - - /* decompose the reloc offset for the plt for ldah+lda */ - hi = plt_index * sizeof(Elf64_External_Rela); - lo = ((hi & 0xffff) ^ 0x8000) - 0x8000; - 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); + insn1 = PLT_ENTRY_WORD1 | ((-(h->plt_offset + 4) >> 2) & 0x1fffff); + insn2 = PLT_ENTRY_WORD2; + insn3 = PLT_ENTRY_WORD3; bfd_put_32 (output_bfd, insn1, splt->contents + h->plt_offset); 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 \ elf64_alpha_mkobject - #define elf_backend_object_p \ elf64_alpha_object_p + #define elf_backend_section_from_shdr \ elf64_alpha_section_from_shdr #define elf_backend_fake_sections \ |