static boolean hppa_handle_PIC_calls
PARAMS ((struct elf_link_hash_entry *, PTR));
+static boolean allocate_plt_and_got
+ PARAMS ((struct elf_link_hash_entry *, PTR));
+
#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
|| RELATIVE_DYNAMIC_RELOCS)
static boolean hppa_discard_copies
#if LONG_BRANCH_VIA_PLT
if (hash != NULL
&& hash->elf.dynindx != -1
- && hash->elf.plt.offset != (bfd_vma) -1)
+ && hash->elf.plt.offset != (bfd_vma) -1
+ && hash->elf.type != STT_PARISC_MILLI)
{
/* If we are doing a shared link and find we need a long
branch stub, then go via the .plt if possible. */
bfd_byte *loc;
bfd_vma sym_value;
bfd_vma insn;
+ bfd_vma off;
int val;
int size;
case hppa_stub_import:
case hppa_stub_import_shared:
- sym_value = (stub_entry->h->elf.plt.offset
+ off = stub_entry->h->elf.plt.offset;
+ if (off >= (bfd_vma) -2)
+ abort ();
+
+ off &= ~ (bfd_vma) 1;
+ sym_value = (off
+ hplink->splt->output_offset
+ hplink->splt->output_section->vma
- elf_gp (hplink->splt->output_section->owner));
dynobj = hplink->root.dynobj;
eh = (struct elf32_hppa_link_hash_entry *) stub_entry->h;
- BFD_ASSERT (eh->elf.root.type == bfd_link_hash_defined
- || eh->elf.root.type == bfd_link_hash_defweak);
+ 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
<__gp>. */
bfd_put_32 (hplink->splt->owner, value,
- hplink->splt->contents + eh->elf.plt.offset);
+ hplink->splt->contents + off);
value = elf_gp (hplink->splt->output_section->owner);
bfd_put_32 (hplink->splt->owner, value,
- hplink->splt->contents + eh->elf.plt.offset + 4);
+ hplink->splt->contents + off + 4);
}
break;
elf32_hppa_object_p (abfd)
bfd *abfd;
{
- unsigned int flags = elf_elfheader (abfd)->e_flags;
+ Elf_Internal_Ehdr * i_ehdrp;
+ unsigned int flags;
+
+ i_ehdrp = elf_elfheader (abfd);
+ if (strcmp (bfd_get_target (abfd), "elf32-hppa-linux") == 0)
+ {
+ if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX)
+ return false;
+ }
+ else
+ {
+ if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
+ return false;
+ }
+ flags = i_ehdrp->e_flags;
switch (flags & (EF_PARISC_ARCH | EF_PARISC_WIDE))
{
case EFA_PARISC_1_0:
case R_PARISC_PLABEL21L:
case R_PARISC_PLABEL32:
/* If the addend is non-zero, we break badly. */
- BFD_ASSERT (rel->r_addend == 0);
+ if (rel->r_addend != 0)
+ abort ();
/* If we are creating a shared library, then we need to
create a PLT entry for all PLABELs, because PLABELs with
local symbols may be passed via a pointer to another
object. Additionally, output a dynamic relocation
- pointing to the PLT entry. */
+ pointing to the PLT entry.
+ For executables, the original 32-bit ABI allowed two
+ different styles of PLABELs (function pointers): For
+ global functions, the PLABEL word points into the .plt
+ two bytes past a (function address, gp) pair, and for
+ local functions the PLABEL points directly at the
+ function. The magic +2 for the first type allows us to
+ differentiate between the two. As you can imagine, this
+ is a real pain when it comes to generating code to call
+ functions indirectly or to compare function pointers.
+ We avoid the mess by always pointing a PLABEL into the
+ .plt, even for local functions. */
need_entry = PLT_PLABEL | NEED_PLT | NEED_DYNREL;
break;
where a symbol is forced local by versioning, or due
to symbolic linking, and we lose the .plt entry. */
need_entry = NEED_PLT | NEED_STUBREL;
+ if (h->elf.type == STT_PARISC_MILLI)
+ need_entry = NEED_STUBREL;
}
break;
&h->elf))
return false;
}
-
- hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
- hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
}
else
h->elf.got.refcount += 1;
memset (local_got_refcounts, -1, size);
}
if (local_got_refcounts[r_symndx] == -1)
- {
- local_got_refcounts[r_symndx] = 1;
-
- hplink->sgot->_raw_size += GOT_ENTRY_SIZE;
- if (info->shared)
- {
- /* If we are generating a shared object, we need to
- output a reloc so that the dynamic linker can
- adjust this GOT entry (because the address
- the shared library is loaded at is not fixed). */
- hplink->srelgot->_raw_size +=
- sizeof (Elf32_External_Rela);
- }
- }
+ local_got_refcounts[r_symndx] = 1;
else
local_got_refcounts[r_symndx] += 1;
}
}
else if (need_entry & PLT_PLABEL)
{
- int indx;
+ bfd_signed_vma *local_plt_refcounts;
if (local_got_refcounts == NULL)
{
elf_local_got_refcounts (abfd) = local_got_refcounts;
memset (local_got_refcounts, -1, size);
}
- indx = r_symndx + symtab_hdr->sh_info;
- if (local_got_refcounts[indx] == -1)
- local_got_refcounts[indx] = 1;
+ local_plt_refcounts = (local_got_refcounts
+ + symtab_hdr->sh_info);
+ if (local_plt_refcounts[r_symndx] == -1)
+ local_plt_refcounts[r_symndx] = 1;
else
- local_got_refcounts[indx] += 1;
+ local_plt_refcounts[r_symndx] += 1;
}
}
}
struct elf_link_hash_entry *h;
struct elf32_hppa_link_hash_table *hplink;
bfd *dynobj;
- asection *sgot;
- asection *srelgot;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (abfd);
if (dynobj == NULL)
return true;
- sgot = hplink->sgot;
- srelgot = hplink->srelgot;
-
relend = relocs + sec->reloc_count;
for (rel = relocs; rel < relend; rel++)
switch ((unsigned int) ELF32_R_TYPE (rel->r_info))
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h->got.refcount > 0)
- {
- h->got.refcount -= 1;
- if (h->got.refcount == 0)
- {
- sgot->_raw_size -= GOT_ENTRY_SIZE;
- srelgot->_raw_size -= sizeof (Elf32_External_Rela);
- }
- }
+ h->got.refcount -= 1;
}
else if (local_got_refcounts != NULL)
{
if (local_got_refcounts[r_symndx] > 0)
- {
- local_got_refcounts[r_symndx] -= 1;
- if (local_got_refcounts[r_symndx] == 0)
- {
- sgot->_raw_size -= GOT_ENTRY_SIZE;
- if (info->shared)
- srelgot->_raw_size -= sizeof (Elf32_External_Rela);
- }
- }
+ local_got_refcounts[r_symndx] -= 1;
}
break;
}
}
+/* This is the condition under which elf32_hppa_finish_dynamic_symbol
+ will be called from elflink.h. If elflink.h doesn't call our
+ finish_dynamic_symbol routine, we'll need to do something about
+ initializing any .plt and .got entries in elf32_hppa_relocate_section. */
+#define WILL_CALL_FINISH_DYNAMIC_SYMBOL(DYN, INFO, H) \
+ ((DYN) \
+ && ((INFO)->shared \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0) \
+ && ((H)->dynindx != -1 \
+ || ((H)->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0))
+
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
}
}
- /* Make an entry in the .plt section. */
- s = hplink->splt;
- h->plt.offset = s->_raw_size;
- if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
- && ((struct elf32_hppa_link_hash_entry *) h)->plabel
- && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
- {
- /* Add some extra space for the dynamic linker to use. */
- s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
- }
- else
- s->_raw_size += PLT_ENTRY_SIZE;
-
if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
{
/* Make sure this symbol is output as a dynamic symbol. */
if (! bfd_elf32_link_record_dynamic_symbol (info, h))
return false;
}
-
- /* We also need to make an entry in the .rela.plt section. */
- s = hplink->srelplt;
- s->_raw_size += sizeof (Elf32_External_Rela);
-
- hplink->need_plt_stub = 1;
}
+
return true;
}
real definition first, and we can just use the same value. */
if (h->weakdef != NULL)
{
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
+ if (h->weakdef->root.type != bfd_link_hash_defined
+ && h->weakdef->root.type != bfd_link_hash_defweak)
+ abort ();
h->root.u.def.section = h->weakdef->root.u.def.section;
h->root.u.def.value = h->weakdef->root.u.def.value;
return true;
static boolean
hppa_handle_PIC_calls (h, inf)
struct elf_link_hash_entry *h;
- PTR inf;
+ PTR inf ATTRIBUTE_UNUSED;
{
- struct bfd_link_info *info;
- bfd *dynobj;
- struct elf32_hppa_link_hash_table *hplink;
- asection *s;
-
if (! (h->plt.refcount > 0
&& (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
((struct elf32_hppa_link_hash_entry *) h)->maybe_pic_call = 1;
((struct elf32_hppa_link_hash_entry *) h)->pic_call = 1;
+ return true;
+}
+
+/* Allocate space in .plt, .got and associated reloc sections for
+ global syms. */
+
+static boolean
+allocate_plt_and_got (h, inf)
+ struct elf_link_hash_entry *h;
+ PTR inf;
+{
+ struct bfd_link_info *info;
+ struct elf32_hppa_link_hash_table *hplink;
+ asection *s;
+
+ if (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ return true;
+
info = (struct bfd_link_info *) inf;
hplink = hppa_link_hash_table (info);
- dynobj = hplink->root.dynobj;
+ if ((hplink->root.dynamic_sections_created
+ && h->plt.refcount > 0)
+ || ((struct elf32_hppa_link_hash_entry *) h)->pic_call)
+ {
+ /* Make an entry in the .plt section. */
+ s = hplink->splt;
+ h->plt.offset = s->_raw_size;
+ if (PLABEL_PLT_ENTRY_SIZE != PLT_ENTRY_SIZE
+ && ((struct elf32_hppa_link_hash_entry *) h)->plabel
+ && (h->elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) == 0)
+ {
+ /* Add some extra space for the dynamic linker to use. */
+ s->_raw_size += PLABEL_PLT_ENTRY_SIZE;
+ }
+ else
+ s->_raw_size += PLT_ENTRY_SIZE;
- /* Make an entry in the .plt section. */
- s = hplink->splt;
- h->plt.offset = s->_raw_size;
- s->_raw_size += PLT_ENTRY_SIZE;
+ if (! ((struct elf32_hppa_link_hash_entry *) h)->pic_call
+ && WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, h))
+ {
+ /* We also need to make an entry in the .rela.plt section. */
+ hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+ hplink->need_plt_stub = 1;
+ }
+ }
+ else
+ {
+ h->plt.offset = (bfd_vma) -1;
+ h->elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
+ }
+
+ if (h->got.refcount > 0)
+ {
+ boolean dyn;
+
+ s = hplink->sgot;
+ h->got.offset = s->_raw_size;
+ s->_raw_size += GOT_ENTRY_SIZE;
+ dyn = hplink->root.dynamic_sections_created;
+ if (WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, h))
+ hplink->srelgot->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ h->got.offset = (bfd_vma) -1;
return true;
}
struct elf_link_hash_entry *h;
struct bfd_link_info *info;
{
- /* Note! We only want to remove these from the dynamic symbol
- table. Therefore we do not set ELF_LINK_FORCED_LOCAL. */
+ /* We only want to remove these from the dynamic symbol table.
+ Therefore we do not leave ELF_LINK_FORCED_LOCAL set. */
if (h->type == STT_PARISC_MILLI)
- elf32_hppa_hide_symbol (info, h);
+ {
+ unsigned short oldflags = h->elf_link_hash_flags;
+ h->elf_link_hash_flags |= ELF_LINK_FORCED_LOCAL;
+ elf32_hppa_hide_symbol (info, h);
+ h->elf_link_hash_flags &= ~ELF_LINK_FORCED_LOCAL;
+ h->elf_link_hash_flags |= oldflags & ELF_LINK_FORCED_LOCAL;
+ }
return true;
}
{
struct elf32_hppa_link_hash_table *hplink;
bfd *dynobj;
+ bfd *i;
asection *s;
boolean relocs;
boolean reltext;
hplink = hppa_link_hash_table (info);
dynobj = hplink->root.dynobj;
- BFD_ASSERT (dynobj != NULL);
+ if (dynobj == NULL)
+ abort ();
if (hplink->root.dynamic_sections_created)
{
- bfd *i;
/* Set the contents of the .interp section to the interpreter. */
if (! info->shared)
{
s = bfd_get_section_by_name (dynobj, ".interp");
- BFD_ASSERT (s != NULL);
+ if (s == NULL)
+ abort ();
s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
elf_link_hash_traverse (&hplink->root,
clobber_millicode_symbols,
info);
+ }
+ else
+ {
+ /* Run through the function symbols, looking for any that are
+ PIC, and allocate space for the necessary .plt entries so
+ that %r19 will be set up. */
+ if (! info->shared)
+ elf_link_hash_traverse (&hplink->root,
+ hppa_handle_PIC_calls,
+ info);
+ }
- /* Set up .plt offsets for local plabels. */
- for (i = info->input_bfds; i; i = i->link_next)
- {
- bfd_signed_vma *local_plt;
- bfd_signed_vma *end_local_plt;
- bfd_size_type locsymcount;
- Elf_Internal_Shdr *symtab_hdr;
+ /* Set up .got and .plt offsets for local syms. */
+ for (i = info->input_bfds; i; i = i->link_next)
+ {
+ bfd_signed_vma *local_got;
+ bfd_signed_vma *end_local_got;
+ bfd_signed_vma *local_plt;
+ bfd_signed_vma *end_local_plt;
+ bfd_size_type locsymcount;
+ Elf_Internal_Shdr *symtab_hdr;
+ asection *srel;
- local_plt = elf_local_got_refcounts (i);
- if (!local_plt)
- continue;
+ if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ continue;
- symtab_hdr = &elf_tdata (i)->symtab_hdr;
- locsymcount = symtab_hdr->sh_info;
- local_plt += locsymcount;
- end_local_plt = local_plt + locsymcount;
+ local_got = elf_local_got_refcounts (i);
+ if (!local_got)
+ continue;
+ symtab_hdr = &elf_tdata (i)->symtab_hdr;
+ locsymcount = symtab_hdr->sh_info;
+ end_local_got = local_got + locsymcount;
+ s = hplink->sgot;
+ srel = hplink->srelgot;
+ for (; local_got < end_local_got; ++local_got)
+ {
+ if (*local_got > 0)
+ {
+ *local_got = s->_raw_size;
+ s->_raw_size += GOT_ENTRY_SIZE;
+ if (info->shared)
+ srel->_raw_size += sizeof (Elf32_External_Rela);
+ }
+ else
+ *local_got = (bfd_vma) -1;
+ }
+
+ local_plt = end_local_got;
+ end_local_plt = local_plt + locsymcount;
+ if (! hplink->root.dynamic_sections_created)
+ {
+ /* Won't be used, but be safe. */
+ for (; local_plt < end_local_plt; ++local_plt)
+ *local_plt = (bfd_vma) -1;
+ }
+ else
+ {
+ s = hplink->splt;
+ srel = hplink->srelplt;
for (; local_plt < end_local_plt; ++local_plt)
{
if (*local_plt > 0)
{
- s = hplink->splt;
*local_plt = s->_raw_size;
s->_raw_size += PLT_ENTRY_SIZE;
if (info->shared)
- hplink->srelplt->_raw_size += sizeof (Elf32_External_Rela);
+ srel->_raw_size += sizeof (Elf32_External_Rela);
}
else
*local_plt = (bfd_vma) -1;
}
}
}
- else
- {
- /* Run through the function symbols, looking for any that are
- PIC, and allocate space for the necessary .plt entries so
- that %r19 will be set up. */
- if (! info->shared)
- elf_link_hash_traverse (&hplink->root,
- hppa_handle_PIC_calls,
- info);
- /* We may have created entries in the .rela.got section.
- However, if we are not creating the dynamic sections, we will
- not actually use these entries. Reset the size of .rela.got,
- which will cause it to get stripped from the output file
- below. */
- hplink->srelgot->_raw_size = 0;
- }
+ /* Allocate global sym .plt and .got entries. */
+ elf_link_hash_traverse (&hplink->root,
+ allocate_plt_and_got,
+ info);
#if ((! LONG_BRANCH_PIC_IN_SHLIB && LONG_BRANCH_VIA_PLT) \
|| RELATIVE_DYNAMIC_RELOCS)
reltext = false;
for (s = dynobj->sections; s != NULL; s = s->next)
{
- const char *name;
-
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
- /* It's OK to base decisions on the section name, because none
- of the dynobj section names depend upon the input files. */
- name = bfd_get_section_name (dynobj, s);
+ if (s == hplink->splt)
+ {
+ if (hplink->need_plt_stub)
+ {
+ /* Make space for the plt stub at the end of the .plt
+ section. We want this stub right at the end, up
+ against the .got section. */
+ int gotalign = bfd_section_alignment (dynobj, hplink->sgot);
+ int pltalign = bfd_section_alignment (dynobj, s);
+ bfd_size_type mask;
- if (strncmp (name, ".rela", 5) == 0)
+ if (gotalign > pltalign)
+ bfd_set_section_alignment (dynobj, s, gotalign);
+ mask = ((bfd_size_type) 1 << gotalign) - 1;
+ s->_raw_size = (s->_raw_size + sizeof (plt_stub) + mask) & ~mask;
+ }
+ }
+ else if (s == hplink->sgot)
+ ;
+ else if (strncmp (bfd_get_section_name (dynobj, s), ".rela", 5) == 0)
{
if (s->_raw_size != 0)
{
/* Remember whether there are any reloc sections other
than .rela.plt. */
- if (strcmp (name+5, ".plt") != 0)
+ if (s != hplink->srelplt)
relocs = true;
/* If this relocation section applies to a read only
s->reloc_count = 0;
}
}
- else if (strcmp (name, ".plt") == 0)
- {
- if (hplink->need_plt_stub)
- {
- /* Make space for the plt stub at the end of the .plt
- section. We want this stub right at the end, up
- against the .got section. */
- int gotalign = bfd_section_alignment (dynobj, hplink->sgot);
- int pltalign = bfd_section_alignment (dynobj, s);
- bfd_size_type mask;
-
- if (gotalign > pltalign)
- bfd_set_section_alignment (dynobj, s, gotalign);
- mask = ((bfd_size_type) 1 << gotalign) - 1;
- s->_raw_size = (s->_raw_size + sizeof (plt_stub) + mask) & ~mask;
- }
- }
- else if (strcmp (name, ".got") == 0)
- ;
else
{
/* It's not one of our sections, so don't allocate space. */
{
asection *s;
- /* Invoke the regular ELF garbage collecting linker to do all the
- work. */
- if (!_bfd_elf32_gc_common_final_link (abfd, info))
+ /* Invoke the regular ELF linker to do all the work. */
+ if (!bfd_elf32_bfd_final_link (abfd, info))
return false;
/* If we're producing a final executable, sort the contents of the
bfd_reloc_status_type r;
const char *sym_name;
boolean plabel;
+ bfd_vma off;
r_type = ELF32_R_TYPE (rel->r_info);
if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
else if (h->elf.root.type == bfd_link_hash_undefweak)
;
else if (info->shared && !info->no_undefined
- && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT)
+ && ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
+ && h->elf.type != STT_PARISC_MILLI)
{
if (info->symbolic)
if (!((*info->callbacks->undefined_symbol)
offset table. */
if (h != NULL)
{
- bfd_vma off;
+ boolean dyn;
off = h->elf.got.offset;
- BFD_ASSERT (off != (bfd_vma) -1);
-
- if (! hplink->root.dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->elf.dynindx == -1)
- && (h->elf.elf_link_hash_flags
- & ELF_LINK_HASH_DEF_REGULAR) != 0))
+ dyn = hplink->root.dynamic_sections_created;
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
{
/* This is actually a static link, or it is a
-Bsymbolic link and the symbol is defined
h->elf.got.offset |= 1;
}
}
-
- relocation = off;
}
else
{
/* Local symbol case. */
- bfd_vma off;
-
- BFD_ASSERT (local_got_offsets != NULL
- && local_got_offsets[r_symndx] != (bfd_vma) -1);
+ if (local_got_offsets == NULL)
+ abort ();
off = local_got_offsets[r_symndx];
if (info->shared)
{
- /* Output a dynamic *ABS* relocation for this
- GOT entry. In this case it is relative to
- the base of the object because the symbol
- index is zero. */
+ /* Output a dynamic relocation for this GOT
+ entry. In this case it is relative to the
+ base of the object because the symbol index
+ is zero. */
Elf_Internal_Rela outrel;
asection *srelgot = hplink->srelgot;
local_got_offsets[r_symndx] |= 1;
}
-
- relocation = off;
}
+ if (off >= (bfd_vma) -2)
+ abort ();
+
/* Add the base of the GOT to the relocation value. */
- relocation += (hplink->sgot->output_offset
- + hplink->sgot->output_section->vma);
+ relocation = (off
+ + hplink->sgot->output_offset
+ + hplink->sgot->output_section->vma);
break;
case R_PARISC_SEGREL32:
case R_PARISC_PLABEL32:
if (hplink->root.dynamic_sections_created)
{
- bfd_vma off;
-
/* If we have a global symbol with a PLT slot, then
redirect this relocation to it. */
if (h != NULL)
{
off = h->elf.plt.offset;
+ if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, info, &h->elf))
+ {
+ /* In a non-shared link, adjust_dynamic_symbols
+ isn't called for symbols forced local. We
+ need to write out the plt entry here. */
+ if ((off & 1) != 0)
+ off &= ~1;
+ else
+ {
+ bfd_put_32 (output_bfd,
+ relocation,
+ hplink->splt->contents + off);
+ bfd_put_32 (output_bfd,
+ elf_gp (hplink->splt->output_section->owner),
+ hplink->splt->contents + off + 4);
+ h->elf.plt.offset |= 1;
+ }
+ }
}
else
{
- int indx;
+ bfd_vma *local_plt_offsets;
+
+ if (local_got_offsets == NULL)
+ abort ();
- indx = r_symndx + symtab_hdr->sh_info;
- off = local_got_offsets[indx];
+ local_plt_offsets = local_got_offsets + symtab_hdr->sh_info;
+ off = local_plt_offsets[r_symndx];
/* As for the local .got entry case, we use the last
bit to record whether we've already initialised
++srelplt->reloc_count;
}
- local_got_offsets[indx] |= 1;
+ local_plt_offsets[r_symndx] |= 1;
}
}
- BFD_ASSERT (off < (bfd_vma) -2);
+ if (off >= (bfd_vma) -2)
+ abort ();
/* PLABELs contain function pointers. Relocation is to
the entry for the function in the .plt. The magic +2
if (name == NULL)
return false;
sreloc = bfd_get_section_by_name (dynobj, name);
- BFD_ASSERT (sreloc != NULL);
+ if (sreloc == NULL)
+ abort ();
}
outrel.r_offset = rel->r_offset;
outrel.r_info = ELF32_R_INFO (indx, r_type);
}
-
+#if 0
+ /* EH info can cause unaligned DIR32 relocs.
+ Tweak the reloc type for the dynamic linker. */
+ if (r_type == R_PARISC_DIR32 && (outrel.r_offset & 3) != 0)
+ outrel.r_info = ELF32_R_INFO (ELF32_R_SYM (outrel.r_info),
+ R_PARISC_DIR32U);
+#endif
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
((Elf32_External_Rela *)
sreloc->contents
{
bfd_vma value;
+ if (h->plt.offset & 1)
+ abort ();
+
/* This symbol has an entry in the procedure linkage table. Set
it up.
{
/* To support lazy linking, the function pointer is
initialised to point to a special stub stored at the
- end of the .plt. This is only done for plt entries
- with a non-*ABS* dynamic relocation. */
+ end of the .plt. This is not done for plt entries
+ with a base-relative dynamic relocation. */
value = (hplink->splt->output_offset
+ hplink->splt->output_section->vma
+ hplink->splt->_raw_size
+ hplink->sgot->output_offset
+ hplink->sgot->output_section->vma);
- /* If this is a static link, or it is a -Bsymbolic link and the
- symbol is defined locally or was forced to be local because
- of a version file, we just want to emit a RELATIVE reloc.
- The entry in the global offset table will already have been
- initialized in the relocate_section function. */
- if (! hplink->root.dynamic_sections_created
- || (info->shared
- && (info->symbolic || h->dynindx == -1)
- && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)))
+ /* If this is a -Bsymbolic link and the symbol is defined
+ locally or was forced to be local because of a version file,
+ we just want to emit a RELATIVE reloc. The entry in the
+ global offset table will already have been initialized in the
+ relocate_section function. */
+ if (info->shared
+ && (info->symbolic || h->dynindx == -1)
+ && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
{
rel.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
rel.r_addend = (h->root.u.def.value
}
else
{
- BFD_ASSERT((h->got.offset & 1) == 0);
+ if ((h->got.offset & 1) != 0)
+ abort ();
bfd_put_32 (output_bfd, (bfd_vma) 0,
hplink->sgot->contents + h->got.offset);
rel.r_info = ELF32_R_INFO (h->dynindx, R_PARISC_DIR32);
/* This symbol needs a copy reloc. Set it up. */
- BFD_ASSERT (h->dynindx != -1
- && (h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak));
+ if (! (h->dynindx != -1
+ && (h->root.type == bfd_link_hash_defined
+ || h->root.type == bfd_link_hash_defweak)))
+ abort ();
s = hplink->srelbss;
{
Elf32_External_Dyn *dyncon, *dynconend;
- BFD_ASSERT (sdyn != NULL);
+ if (sdyn == NULL)
+ abort ();
dyncon = (Elf32_External_Dyn *) sdyn->contents;
dynconend = (Elf32_External_Dyn *) (sdyn->contents + sdyn->_raw_size);