This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Fix elf32-hppa as HJ did for elf32-i386
- To: binutils at sourceware dot cygnus dot com
- Subject: Fix elf32-hppa as HJ did for elf32-i386
- From: Alan Modra <amodra at bigpond dot net dot au>
- Date: Thu, 21 Jun 2001 15:30:17 +0930
elf32-hppa.c has the same problem as elf32-i386.c, not surprisingly
since I inserted both bits of buggy code. Worse, for hppa I was
foolish enough to put the code on the 2.11 branch. Apparently, not
as many people as I thought were actually using my latest code on
hppa-linux. :-(
bfd/ChangeLog
* elf32-hppa.c (elf32_hppa_size_dynamic_sections): Always
allocate local .got space. Use shortcuts from hash table for .got
and .plt rather than comparing section names.
(elf32_hppa_check_relocs): Use local_plt_refcounts var rather than
adjusting index into local_got_refcounts to document what we are
really doing.
(elf32_hppa_relocate_section): Similarly for local_plt_offsets.
Tidy .got and .plt error checking.
--
Alan Modra
Index: bfd/elf32-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-hppa.c,v
retrieving revision 1.38
diff -u -p -r1.38 elf32-hppa.c
--- elf32-hppa.c 2001/06/05 04:39:31 1.38
+++ elf32-hppa.c 2001/06/21 05:29:59
@@ -1522,7 +1522,7 @@ elf32_hppa_check_relocs (abfd, info, sec
}
else if (need_entry & PLT_PLABEL)
{
- int indx;
+ bfd_signed_vma *local_plt_refcounts;
if (local_got_refcounts == NULL)
{
@@ -1538,11 +1538,12 @@ elf32_hppa_check_relocs (abfd, info, sec
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;
}
}
}
@@ -2215,6 +2216,7 @@ elf32_hppa_size_dynamic_sections (output
{
struct elf32_hppa_link_hash_table *hplink;
bfd *dynobj;
+ bfd *i;
asection *s;
boolean relocs;
boolean reltext;
@@ -2226,7 +2228,6 @@ elf32_hppa_size_dynamic_sections (output
if (hplink->root.dynamic_sections_created)
{
- bfd *i;
/* Set the contents of the .interp section to the interpreter. */
if (! info->shared)
@@ -2242,45 +2243,64 @@ elf32_hppa_size_dynamic_sections (output
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 .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;
+ /* 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;
- if (bfd_get_flavour (i) != bfd_target_elf_flavour)
- continue;
+ if (bfd_get_flavour (i) != bfd_target_elf_flavour)
+ continue;
- local_got = elf_local_got_refcounts (i);
- if (!local_got)
- continue;
+ 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)
+ 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)
{
- 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_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;
+ 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)
@@ -2297,16 +2317,6 @@ elf32_hppa_size_dynamic_sections (output
}
}
}
- 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);
- }
/* Allocate global sym .plt and .got entries. */
elf_link_hash_traverse (&hplink->root,
@@ -2332,16 +2342,29 @@ elf32_hppa_size_dynamic_sections (output
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)
{
@@ -2350,7 +2373,7 @@ elf32_hppa_size_dynamic_sections (output
/* 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
@@ -2368,25 +2391,6 @@ elf32_hppa_size_dynamic_sections (output
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. */
@@ -3587,6 +3591,7 @@ elf32_hppa_relocate_section (output_bfd,
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)
@@ -3690,13 +3695,9 @@ elf32_hppa_relocate_section (output_bfd,
offset table. */
if (h != NULL)
{
- bfd_vma off;
boolean dyn;
off = h->elf.got.offset;
- if (off == (bfd_vma) -1)
- abort ();
-
dyn = hplink->root.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, info, &h->elf))
{
@@ -3721,18 +3722,15 @@ elf32_hppa_relocate_section (output_bfd,
h->elf.got.offset |= 1;
}
}
-
- relocation = off;
}
else
{
/* Local symbol case. */
- bfd_vma off;
-
- if (local_got_offsets == NULL
- || (off = local_got_offsets[r_symndx]) == (bfd_vma) -1)
+ if (local_got_offsets == NULL)
abort ();
+ off = local_got_offsets[r_symndx];
+
/* The offset must always be a multiple of 4. We use
the least significant bit to record whether we have
already generated the necessary reloc. */
@@ -3766,13 +3764,15 @@ elf32_hppa_relocate_section (output_bfd,
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:
@@ -3789,8 +3789,6 @@ elf32_hppa_relocate_section (output_bfd,
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)
@@ -3817,10 +3815,13 @@ elf32_hppa_relocate_section (output_bfd,
}
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
@@ -3855,11 +3856,11 @@ elf32_hppa_relocate_section (output_bfd,
++srelplt->reloc_count;
}
- local_got_offsets[indx] |= 1;
+ local_plt_offsets[r_symndx] |= 1;
}
}
- if (off >= (bfd_vma) -2 || (off & 1) != 0)
+ if (off >= (bfd_vma) -2)
abort ();
/* PLABELs contain function pointers. Relocation is to