aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-hppa.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/elf64-hppa.c')
-rw-r--r--bfd/elf64-hppa.c121
1 files changed, 76 insertions, 45 deletions
diff --git a/bfd/elf64-hppa.c b/bfd/elf64-hppa.c
index 3f5a3fe..6a63ce2 100644
--- a/bfd/elf64-hppa.c
+++ b/bfd/elf64-hppa.c
@@ -247,6 +247,24 @@ static bool get_stub
static int elf64_hppa_elf_get_symbol_type
(Elf_Internal_Sym *, int);
+/* Search for the index of a global symbol in it's defining object file. */
+
+static long
+global_sym_index (struct elf_link_hash_entry *h)
+{
+ struct elf_link_hash_entry **p;
+ bfd *obj;
+
+ BFD_ASSERT (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak);
+
+ obj = h->root.u.def.section->owner;
+ for (p = elf_sym_hashes (obj); *p != h; ++p)
+ continue;
+
+ return p - elf_sym_hashes (obj) + elf_tdata (obj)->symtab_hdr.sh_info;
+}
+
/* Initialize an entry in the link hash table. */
static struct bfd_hash_entry *
@@ -641,7 +659,10 @@ elf64_hppa_check_relocs (bfd *abfd,
/* PR15323, ref flags aren't set for references in the same
object. */
- hh->eh.ref_regular = 1;
+ if (!hh->eh.root.linker_def && !hh->eh.root.ldscript_def)
+ hh->eh.ref_regular = 1;
+ else
+ hh = NULL;
}
else
hh = NULL;
@@ -744,7 +765,7 @@ elf64_hppa_check_relocs (bfd *abfd,
case R_PARISC_LTOFF_FPTR16WF:
case R_PARISC_LTOFF_FPTR16DF:
if (bfd_link_pic (info) || maybe_dynamic)
- need_entry = (NEED_DLT | NEED_OPD | NEED_PLT);
+ need_entry = (NEED_DLT | NEED_OPD | NEED_PLT | NEED_DYNREL);
else
need_entry = (NEED_DLT | NEED_OPD | NEED_PLT);
dynrel_type = R_PARISC_FPTR64;
@@ -762,9 +783,7 @@ elf64_hppa_check_relocs (bfd *abfd,
/* Add more cases as needed. */
}
- if (!need_entry)
- continue;
-
+ /* We may need this information later for OPD. */
if (hh)
{
/* Stash away enough information to be able to find this symbol
@@ -773,6 +792,9 @@ elf64_hppa_check_relocs (bfd *abfd,
hh->sym_indx = r_symndx;
}
+ if (!need_entry)
+ continue;
+
/* Create what's needed. */
if (need_entry & NEED_DLT)
{
@@ -874,6 +896,13 @@ elf64_hppa_check_relocs (bfd *abfd,
sec_symndx, rel->r_offset, rel->r_addend))
goto err_out;
+ /* Add symbol to dynamic symbol table. */
+ if (hh != NULL
+ && bfd_link_pic (info)
+ && ! (bfd_elf_link_record_local_dynamic_symbol
+ (info, abfd, r_symndx)))
+ goto err_out;
+
/* If we are building a shared library and we just recorded
a dynamic R_PARISC_FPTR64 relocation, then make sure the
section symbol for this section ends up in the dynamic
@@ -881,7 +910,7 @@ elf64_hppa_check_relocs (bfd *abfd,
if (bfd_link_pic (info) && dynrel_type == R_PARISC_FPTR64
&& ! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, sec_symndx)))
- return false;
+ goto err_out;
}
}
@@ -969,10 +998,14 @@ allocate_global_data_dlt (struct elf_link_hash_entry *eh, void *data)
against it. */
if (eh->dynindx == -1 && eh->type != STT_PARISC_MILLI)
{
- bfd *owner = eh->root.u.def.section->owner;
+ if (!hh->owner)
+ {
+ hh->owner = eh->root.u.def.section->owner;
+ hh->sym_indx = global_sym_index (eh);
+ }
if (! (bfd_elf_link_record_local_dynamic_symbol
- (x->info, owner, hh->sym_indx)))
+ (x->info, hh->owner, hh->sym_indx)))
return false;
}
}
@@ -983,7 +1016,7 @@ allocate_global_data_dlt (struct elf_link_hash_entry *eh, void *data)
return true;
}
-/* Allocate space for a DLT.PLT entry. */
+/* Allocate space for a PLT entry. */
static bool
allocate_global_data_plt (struct elf_link_hash_entry *eh, void *data)
@@ -1046,37 +1079,41 @@ allocate_global_data_opd (struct elf_link_hash_entry *eh, void *data)
struct elf64_hppa_link_hash_entry *hh = hppa_elf_hash_entry (eh);
struct elf64_hppa_allocate_data *x = (struct elf64_hppa_allocate_data *)data;
- if (hh && hh->want_opd)
+ if (hh->want_opd)
{
/* We never need an opd entry for a symbol which is not
defined by this output file. */
- if (hh && (hh->eh.root.type == bfd_link_hash_undefined
- || hh->eh.root.type == bfd_link_hash_undefweak
- || hh->eh.root.u.def.section->output_section == NULL))
- hh->want_opd = 0;
+ if (hh->eh.root.type == bfd_link_hash_undefined
+ || hh->eh.root.type == bfd_link_hash_undefweak
+ || hh->eh.root.u.def.section->output_section == NULL)
+ {
+ hh->want_opd = 0;
+ return true;
+ }
/* If we are creating a shared library, took the address of a local
function or might export this function from this object file, then
we have to create an opd descriptor. */
- else if (bfd_link_pic (x->info)
- || hh == NULL
- || (hh->eh.dynindx == -1 && hh->eh.type != STT_PARISC_MILLI)
- || (hh->eh.root.type == bfd_link_hash_defined
- || hh->eh.root.type == bfd_link_hash_defweak))
+ if (bfd_link_pic (x->info)
+ || (hh->eh.dynindx == -1 && hh->eh.type != STT_PARISC_MILLI)
+ || hh->eh.root.type == bfd_link_hash_defined
+ || hh->eh.root.type == bfd_link_hash_defweak)
{
/* If we are creating a shared library, then we will have to
create a runtime relocation for the symbol to properly
initialize the .opd entry. Make sure the symbol gets
added to the dynamic symbol table. */
- if (bfd_link_pic (x->info)
- && (hh == NULL || (hh->eh.dynindx == -1)))
+ if (bfd_link_pic (x->info) && hh->eh.dynindx == -1)
{
- bfd *owner;
/* PR 6511: Default to using the dynamic symbol table. */
- owner = (hh->owner ? hh->owner: eh->root.u.def.section->owner);
+ if (!hh->owner)
+ {
+ hh->owner = eh->root.u.def.section->owner;
+ hh->sym_indx = global_sym_index (eh);
+ }
if (!bfd_elf_link_record_local_dynamic_symbol
- (x->info, owner, hh->sym_indx))
+ (x->info, hh->owner, hh->sym_indx))
return false;
}
@@ -1419,15 +1456,8 @@ allocate_dynrel_entries (struct elf_link_hash_entry *eh, void *data)
if (!shared && rent->type == R_PARISC_FPTR64 && hh->want_opd)
continue;
- hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela);
-
- /* Make sure this symbol gets into the dynamic symbol table if it is
- not already recorded. ?!? This should not be in the loop since
- the symbol need only be added once. */
- if (eh->dynindx == -1 && eh->type != STT_PARISC_MILLI)
- if (!bfd_elf_link_record_local_dynamic_symbol
- (x->info, rent->sec->owner, hh->sym_indx))
- return false;
+ if (!discarded_section (hppa_info->other_rel_sec))
+ hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela);
}
/* Take care of the GOT and PLT relocations. */
@@ -1555,7 +1585,7 @@ elf64_hppa_late_size_sections (bfd *output_bfd, struct bfd_link_info *info)
/* Set the contents of the .interp section to the interpreter. */
if (bfd_link_executable (info) && !info->nointerp)
{
- sec = bfd_get_linker_section (dynobj, ".interp");
+ sec = hppa_info->root.interp;
BFD_ASSERT (sec != NULL);
sec->size = sizeof ELF_DYNAMIC_INTERPRETER;
sec->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
@@ -2200,11 +2230,7 @@ elf64_hppa_finalize_dlt (struct elf_link_hash_entry *eh, void *data)
sdlt = hppa_info->dlt_sec;
sdltrel = hppa_info->dlt_rel_sec;
- /* H/DYN_H may refer to a local variable and we know it's
- address, so there is no need to create a relocation. Just install
- the proper value into the DLT, note this shortcut can not be
- skipped when building a shared library. */
- if (! bfd_link_pic (info) && hh && hh->want_dlt)
+ if (! bfd_link_pic (info) && hh->want_dlt)
{
bfd_vma value;
@@ -2293,15 +2319,18 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
if (!dynamic_symbol && !bfd_link_pic (info))
return true;
+ hppa_info = hppa_link_hash_table (info);
+ if (hppa_info == NULL)
+ return false;
+
+ if (discarded_section (hppa_info->other_rel_sec))
+ return true;
+
if (hh->reloc_entries)
{
struct elf64_hppa_dyn_reloc_entry *rent;
int dynindx;
- hppa_info = hppa_link_hash_table (info);
- if (hppa_info == NULL)
- return false;
-
/* We may need to do a relocation against a local symbol, in
which case we have to look up it's dynamic symbol index off
the local symbol hash table. */
@@ -2382,6 +2411,7 @@ elf64_hppa_finalize_dynreloc (struct elf_link_hash_entry *eh,
else
rel.r_addend = rent->addend;
+ BFD_ASSERT (dynindx != -1);
rel.r_info = ELF64_R_INFO (dynindx, rent->type);
loc = hppa_info->other_rel_sec->contents;
@@ -3162,7 +3192,7 @@ elf_hppa_final_link_relocate (Elf_Internal_Rela *rel,
switch (r_type)
{
case R_PARISC_NONE:
- break;
+ return bfd_reloc_ok;
/* Basic function call support.
@@ -3865,7 +3895,8 @@ elf64_hppa_relocate_section (bfd *output_bfd,
if (sym_sec != NULL && discarded_section (sym_sec))
RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
- rel, 1, relend, howto, 0, contents);
+ rel, 1, relend, R_PARISC_NONE,
+ howto, 0, contents);
if (bfd_link_relocatable (info))
continue;