diff options
author | Dave Anglin <dave.anglin@nrc.ca> | 2003-09-10 18:46:08 +0000 |
---|---|---|
committer | Dave Anglin <dave.anglin@nrc.ca> | 2003-09-10 18:46:08 +0000 |
commit | a252afa4cdffd95d8c64453bb808db005796f24e (patch) | |
tree | 6c8f0d8687f3dfdd24080c0f5759cbc6b3b95048 /bfd/elf32-hppa.c | |
parent | dcc6aaff9c3e48213807e41726275df35ce8a20b (diff) | |
download | fsf-binutils-gdb-a252afa4cdffd95d8c64453bb808db005796f24e.zip fsf-binutils-gdb-a252afa4cdffd95d8c64453bb808db005796f24e.tar.gz fsf-binutils-gdb-a252afa4cdffd95d8c64453bb808db005796f24e.tar.bz2 |
* elf32-hppa.c (struct elf32_hppa_link_hash_entry,
hppa_link_hash_newfunc, hppa_build_one_stub,
elf32_hppa_adjust_dynamic_symbol, mark_PIC_calls, allocate_plt_static,
allocate_dynrelocs, elf32_hppa_size_dynamic_sections,
elf32_hppa_finish_dynamic_symbol): Remove pic_call field and all code
for generating import stubs for calls to statically linked PIC
functions.
(hppa_type_of_stub): Don't generate an import stub for calls to
statically linked pic functions. Generate import stubs for calls
in a shared object, to functions not in a regular file, and to
defined weak functions. Add new argument INFO.
(hppa_build_one_stub): Don't undef ADDIL_DP.
(elf32_hppa_check_relocs): Don't set SEC_HAS_GOT_REF flag.
(elf32_hppa_size_stubs): Pass info to hppa_type_of_stub.
(final_link_relocate): Change all DLTIND relocs to DPREL relocs in a
non-shared link. Convert instructions that use the the linkage table
pointer, or a facsimile thereof, to use the global data pointer when
the reloc has been changed.
Diffstat (limited to 'bfd/elf32-hppa.c')
-rw-r--r-- | bfd/elf32-hppa.c | 234 |
1 files changed, 90 insertions, 144 deletions
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 924f7af..be0727f 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -203,10 +203,6 @@ struct elf32_hppa_link_hash_entry { #endif } *dyn_relocs; - /* Set if the only reason we need a .plt entry is for a non-PIC to - PIC function call. */ - unsigned int pic_call:1; - /* Set if this symbol is used by a plabel reloc. */ unsigned int plabel:1; }; @@ -345,7 +341,6 @@ hppa_link_hash_newfunc (struct bfd_hash_entry *entry, eh = (struct elf32_hppa_link_hash_entry *) entry; eh->stub_cache = NULL; eh->dyn_relocs = NULL; - eh->pic_call = 0; eh->plabel = 0; } @@ -556,7 +551,8 @@ static enum elf32_hppa_stub_type hppa_type_of_stub (asection *input_sec, const Elf_Internal_Rela *rel, struct elf32_hppa_link_hash_entry *hash, - bfd_vma destination) + bfd_vma destination, + struct bfd_link_info *info) { bfd_vma location; bfd_vma branch_offset; @@ -565,8 +561,11 @@ hppa_type_of_stub (asection *input_sec, if (hash != NULL && hash->elf.plt.offset != (bfd_vma) -1 - && (hash->elf.dynindx != -1 || hash->pic_call) - && !hash->plabel) + && hash->elf.dynindx != -1 + && !hash->plabel + && (info->shared + || !(hash->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) + || hash->elf.root.type == bfd_link_hash_defweak)) { /* We need an import stub. Decide between hppa_stub_import and hppa_stub_import_shared later. */ @@ -769,39 +768,6 @@ hppa_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) size = 16; } - if (!info->shared - && stub_entry->h != NULL - && stub_entry->h->pic_call) - { - /* Build the .plt entry needed to call a PIC function from - statically linked code. We don't need any relocs. */ - bfd *dynobj; - struct elf32_hppa_link_hash_entry *eh; - bfd_vma value; - - dynobj = htab->elf.dynobj; - eh = (struct elf32_hppa_link_hash_entry *) stub_entry->h; - - if (eh->elf.root.type != bfd_link_hash_defined - && eh->elf.root.type != bfd_link_hash_defweak) - abort (); - - value = (eh->elf.root.u.def.value - + eh->elf.root.u.def.section->output_offset - + eh->elf.root.u.def.section->output_section->vma); - - /* Fill in the entry in the procedure linkage table. - - The format of a plt entry is - <funcaddr> - <__gp>. */ - - bfd_put_32 (htab->splt->owner, value, - htab->splt->contents + off); - value = elf_gp (htab->splt->output_section->owner); - bfd_put_32 (htab->splt->owner, value, - htab->splt->contents + off + 4); - } break; case hppa_stub_export: @@ -863,7 +829,6 @@ hppa_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg) #undef BL_R1 #undef ADDIL_R1 #undef DEPI_R1 -#undef ADDIL_DP #undef LDW_R1_R21 #undef LDW_R1_DLT #undef LDW_R1_R19 @@ -1100,9 +1065,6 @@ elf32_hppa_check_relocs (bfd *abfd, case R_PARISC_DLTIND21L: /* This symbol requires a global offset table entry. */ need_entry = NEED_GOT; - - /* Mark this section as containing PIC code. */ - sec->flags |= SEC_HAS_GOT_REF; break; case R_PARISC_PLABEL14R: /* "Official" procedure labels. */ @@ -1685,18 +1647,8 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, used by a plabel relocation. Either this object is the application or we are doing a shared symbolic link. */ - /* As a special sop to the hppa ABI, we keep a .plt entry - for functions in sections containing PIC code. */ - if (!info->shared - && h->plt.refcount > 0 - && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) != 0 - && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0) - ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1; - else - { - h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - } + h->plt.offset = (bfd_vma) -1; + h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; } return TRUE; @@ -1796,34 +1748,8 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info, return TRUE; } -/* Called via elf_link_hash_traverse to create .plt entries for an - application that uses statically linked PIC functions. Similar to - the first part of elf32_hppa_adjust_dynamic_symbol. */ - -static bfd_boolean -mark_PIC_calls (struct elf_link_hash_entry *h, void *inf ATTRIBUTE_UNUSED) -{ - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if (! (h->plt.refcount > 0 - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && (h->root.u.def.section->flags & SEC_HAS_GOT_REF) != 0)) - { - h->plt.offset = (bfd_vma) -1; - h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT; - return TRUE; - } - - h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT; - ((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1; - - return TRUE; -} - /* Allocate space in the .plt for entries that won't have relocations. - ie. pic_call and plabel entries. */ + ie. plabel entries. */ static bfd_boolean allocate_plt_static (struct elf_link_hash_entry *h, void *inf) @@ -1840,16 +1766,7 @@ allocate_plt_static (struct elf_link_hash_entry *h, void *inf) info = inf; htab = hppa_link_hash_table (info); - if (((struct elf32_hppa_link_hash_entry *) h)->pic_call) - { - /* Make an entry in the .plt section for non-pic code that is - calling pic code. */ - ((struct elf32_hppa_link_hash_entry *) h)->plabel = 0; - s = htab->splt; - h->plt.offset = s->_raw_size; - s->_raw_size += PLT_ENTRY_SIZE; - } - else if (htab->elf.dynamic_sections_created + if (htab->elf.dynamic_sections_created && h->plt.refcount > 0) { /* Make sure this symbol is output as a dynamic symbol. @@ -1916,7 +1833,6 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) htab = hppa_link_hash_table (info); if (htab->elf.dynamic_sections_created && h->plt.offset != (bfd_vma) -1 - && !((struct elf32_hppa_link_hash_entry *) h)->pic_call && !((struct elf32_hppa_link_hash_entry *) h)->plabel) { /* Make an entry in the .plt section. */ @@ -2114,14 +2030,6 @@ elf32_hppa_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, clobber_millicode_symbols, info); } - else - { - /* Run through the function symbols, looking for any that are - PIC, and mark them as needing .plt entries so that %r19 will - be set up. */ - if (! info->shared) - elf_link_hash_traverse (&htab->elf, mark_PIC_calls, info); - } /* Set up .got and .plt offsets for local syms, and space for local dynamic relocs. */ @@ -2871,7 +2779,7 @@ elf32_hppa_size_stubs /* Determine what (if any) linker stub is needed. */ stub_type = hppa_type_of_stub (section, irela, hash, - destination); + destination, info); if (stub_type == hppa_stub_none) continue; @@ -3126,10 +3034,12 @@ final_link_relocate (asection *input_section, bfd_vma value, struct elf32_hppa_link_hash_table *htab, asection *sym_sec, - struct elf32_hppa_link_hash_entry *h) + struct elf32_hppa_link_hash_entry *h, + struct bfd_link_info *info) { int insn; unsigned int r_type = ELF32_R_TYPE (rel->r_info); + unsigned int orig_r_type = r_type; reloc_howto_type *howto = elf_hppa_howto_table + r_type; int r_format = howto->bitsize; enum hppa_reloc_field_selector_type_alt r_field; @@ -3152,6 +3062,26 @@ final_link_relocate (asection *input_section, input_section->output_offset + input_section->output_section->vma); + /* If we are not building a shared library, convert DLTIND relocs to + DPREL relocs. */ + if (!info->shared) + { + switch (r_type) + { + case R_PARISC_DLTIND21L: + r_type = R_PARISC_DPREL21L; + break; + + case R_PARISC_DLTIND14R: + r_type = R_PARISC_DPREL14R; + break; + + case R_PARISC_DLTIND14F: + r_type = R_PARISC_DPREL14F; + break; + } + } + switch (r_type) { case R_PARISC_PCREL12F: @@ -3163,8 +3093,11 @@ final_link_relocate (asection *input_section, || sym_sec->output_section == NULL || (h != NULL && h->elf.plt.offset != (bfd_vma) -1 - && (h->elf.dynindx != -1 || h->pic_call) - && !h->plabel)) + && h->elf.dynindx != -1 + && !h->plabel + && (info->shared + || !(h->elf.elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) + || h->elf.root.type == bfd_link_hash_defweak))) { stub_entry = hppa_get_stub_entry (input_section, sym_sec, h, rel, htab); @@ -3204,6 +3137,38 @@ final_link_relocate (asection *input_section, case R_PARISC_DPREL21L: case R_PARISC_DPREL14R: case R_PARISC_DPREL14F: + /* Convert instructions that use the linkage table pointer (r19) to + instructions that use the global data pointer (dp). This is the + most efficient way of using PIC code in an incomplete executable, + but the user must follow the standard runtime conventions for + accessing data for this to work. */ + if (orig_r_type == R_PARISC_DLTIND21L) + { + /* Convert addil instructions if the original reloc was a + DLTIND21L. GCC sometimes uses a register other than r19 for + the operation, so we must convert any addil instruction + that uses this relocation. */ + if ((insn & 0xfc000000) == ((int) OP_ADDIL << 26)) + insn = ADDIL_DP; + else + /* We must have a ldil instruction. It's too hard to find + and convert the associated add instruction, so issue an + error. */ + (*_bfd_error_handler) + (_("%s(%s+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"), + bfd_archive_filename (input_bfd), + input_section->name, + (long) rel->r_offset, + howto->name, + insn); + } + else if (orig_r_type == R_PARISC_DLTIND14F) + { + /* This must be a format 1 load/store. Change the base + register to dp. */ + insn = (insn & 0xfc1ffff) | (27 << 21); + } + /* For all the DP relative relocations, we need to examine the symbol's section. If it has no section or if it's a code section, then "data pointer relative" makes no sense. In that case we don't @@ -3806,7 +3771,7 @@ elf32_hppa_relocate_section (bfd *output_bfd, } r = final_link_relocate (input_section, contents, rel, relocation, - htab, sym_sec, h); + htab, sym_sec, h, info); if (r == bfd_reloc_ok) continue; @@ -3863,6 +3828,8 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Sym *sym) { struct elf32_hppa_link_hash_table *htab; + Elf_Internal_Rela rel; + bfd_byte *loc; htab = hppa_link_hash_table (info); @@ -3890,43 +3857,27 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd, + h->root.u.def.section->output_section->vma); } - if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call) + /* Create a dynamic IPLT relocation for this entry. */ + rel.r_offset = (h->plt.offset + + htab->splt->output_offset + + htab->splt->output_section->vma); + if (h->dynindx != -1) { - Elf_Internal_Rela rel; - bfd_byte *loc; - - /* Create a dynamic IPLT relocation for this entry. */ - rel.r_offset = (h->plt.offset - + htab->splt->output_offset - + htab->splt->output_section->vma); - if (h->dynindx != -1) - { - rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT); - rel.r_addend = 0; - } - else - { - /* This symbol has been marked to become local, and is - used by a plabel so must be kept in the .plt. */ - rel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT); - rel.r_addend = value; - } - - loc = htab->srelplt->contents; - loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela); - bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, - &rel, loc); + rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_IPLT); + rel.r_addend = 0; } else { - bfd_put_32 (htab->splt->owner, - value, - htab->splt->contents + h->plt.offset); - bfd_put_32 (htab->splt->owner, - elf_gp (htab->splt->output_section->owner), - htab->splt->contents + h->plt.offset + 4); + /* This symbol has been marked to become local, and is + used by a plabel so must be kept in the .plt. */ + rel.r_info = ELF32_R_INFO (0, R_PARISC_IPLT); + rel.r_addend = value; } + loc = htab->srelplt->contents; + loc += htab->srelplt->reloc_count++ * sizeof (Elf32_External_Rela); + bfd_elf32_swap_reloca_out (htab->splt->output_section->owner, &rel, loc); + if ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { /* Mark the symbol as undefined, rather than as defined in @@ -3937,9 +3888,6 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd, if (h->got.offset != (bfd_vma) -1) { - Elf_Internal_Rela rel; - bfd_byte *loc; - /* This symbol has an entry in the global offset table. Set it up. */ @@ -3978,8 +3926,6 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd, if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_COPY) != 0) { asection *s; - Elf_Internal_Rela rel; - bfd_byte *loc; /* This symbol needs a copy reloc. Set it up. */ |