This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Fix ld segfaults under hppa64-hp-hpux11
- From: "John David Anglin" <dave at hiauly1 dot hia dot nrc dot ca>
- To: binutils at sources dot redhat dot com
- Cc: ross dot alexander at uk dot neceur dot com, law at redhat dot com, amodra at bigpond dot net dot au
- Date: Wed, 12 Jun 2002 12:43:37 -0400 (EDT)
- Subject: Fix ld segfaults under hppa64-hp-hpux11
The enclosed patch fixes the two problems noted by Ross Alexander in this
message <http://sources.redhat.com/ml/binutils/2002-06/msg00029.html>.
PROBLEM 1 - BUILDING SHARED LIBRARIES WITH UNDEFINED FUNCTION REFERENCES
This was the more complicated of the two. The problem was we were trying
to create an opd for "f1" when linking libtest2.sl when we shouldn't.
f1 is not defined in libtest2.sl (it is defined in libtest1.sl) so we
shouldn't try to create an opd entry for it when we link libtest2.sl.
Thus, I changed allocate_global_data_opd to not request an opd entry
when a symbol has no output section. This fixed the segfault but a
simple application linked against libtest2.sl segfaulted when a call
with (*r1) was performed. A check to see if we want an opd entry
needed to be added to elf64_hppa_finalize_dynreloc to fix this problem.
PROBLEM 2 - BUILDING EXECUTABLE WITH UNDEFINED FUNCTION REFERENCE
We probably shouldn't be creating a dlt entry for an undefined function
reference. However, since an error condition has already occurred,
I simply added a check to see if the section pointer for the symbol
was not NULL to prevent the segfault.
I have tested the patch on Ross's two examples. I have also tested
the patch with a rebuild of binutils and gcc on hppa64-hp-hpux11.00.
Please install if OK.
Dave
--
J. David Anglin dave.anglin@nrc.ca
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2002-06-12 John David Anglin <dave@hiauly1.hia.nrc.ca>
* elf64-hppa.c (allocate_global_data_opd): We don't need an opd entry
for a symbol that has no output section.
(allocate_dynrel_entries): Correct comment.
(elf64_hppa_finalize_dynreloc): Likewise. Don't create an opd entry
unless we want one.
(elf64_hppa_finalize_opd): Prevent segfault if dyn_h is NULL.
(elf64_hppa_finalize_dlt): Likewise. Prevent segfault for symbols
with no section. Remove unnecessary parentheses.
Index: elf64-hppa.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-hppa.c,v
retrieving revision 1.21
diff -u -3 -p -r1.21 elf64-hppa.c
--- elf64-hppa.c 6 Jun 2002 00:29:21 -0000 1.21
+++ elf64-hppa.c 12 Jun 2002 16:00:01 -0000
@@ -1159,7 +1159,8 @@ allocate_global_data_opd (dyn_h, data)
/* We never need an opd entry for a symbol which is not
defined by this output file. */
- if (h && h->root.type == bfd_link_hash_undefined)
+ if (h && (h->root.type == bfd_link_hash_undefined
+ || h->root.u.def.section->output_section == NULL))
dyn_h->want_opd = 0;
/* If we are creating a shared library, took the address of a local
@@ -1168,9 +1169,8 @@ allocate_global_data_opd (dyn_h, data)
else if (x->info->shared
|| h == NULL
|| h->dynindx == -1
- || ((h->root.type == bfd_link_hash_defined
- || h->root.type == bfd_link_hash_defweak)
- && h->root.u.def.section->output_section != NULL))
+ || (h->root.type == bfd_link_hash_defined
+ || h->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
@@ -1535,9 +1535,8 @@ allocate_dynrel_entries (dyn_h, data)
switch (rent->type)
{
case R_PARISC_FPTR64:
- /* Allocate one iff we are not building a shared library and
- !want_opd, which by this point will be true only if we're
- actually allocating one statically in the main executable. */
+ /* Allocate one iff we are building a shared library and don't
+ want an opd entry. */
if (!x->info->shared && dyn_h->want_opd)
continue;
break;
@@ -2115,7 +2114,7 @@ elf64_hppa_finalize_opd (dyn_h, data)
{
struct bfd_link_info *info = (struct bfd_link_info *)data;
struct elf64_hppa_link_hash_table *hppa_info;
- struct elf_link_hash_entry *h = dyn_h->h;
+ struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
asection *sopd;
asection *sopdrel;
@@ -2123,7 +2122,7 @@ elf64_hppa_finalize_opd (dyn_h, data)
sopd = hppa_info->opd_sec;
sopdrel = hppa_info->opd_rel_sec;
- if (h && dyn_h && dyn_h->want_opd)
+ if (h && dyn_h->want_opd)
{
bfd_vma value;
@@ -2236,7 +2235,7 @@ elf64_hppa_finalize_dlt (dyn_h, data)
struct bfd_link_info *info = (struct bfd_link_info *)data;
struct elf64_hppa_link_hash_table *hppa_info;
asection *sdlt, *sdltrel;
- struct elf_link_hash_entry *h = dyn_h->h;
+ struct elf_link_hash_entry *h = dyn_h ? dyn_h->h : NULL;
hppa_info = elf64_hppa_hash_table (info);
@@ -2247,7 +2246,7 @@ elf64_hppa_finalize_dlt (dyn_h, data)
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 (! info->shared && h && dyn_h && dyn_h->want_dlt)
+ if (! info->shared && h && dyn_h->want_dlt)
{
bfd_vma value;
@@ -2263,16 +2262,17 @@ elf64_hppa_finalize_dlt (dyn_h, data)
+ hppa_info->opd_sec->output_offset
+ hppa_info->opd_sec->output_section->vma);
}
- else
+ else if (h->root.u.def.section)
{
- value = (h->root.u.def.value
- + h->root.u.def.section->output_offset);
-
+ value = h->root.u.def.value + h->root.u.def.section->output_offset;
if (h->root.u.def.section->output_section)
value += h->root.u.def.section->output_section->vma;
else
value += h->root.u.def.section->vma;
}
+ else
+ /* We have an undefined function reference. */
+ value = 0;
/* We do not need to include the output offset of the DLT section
here because we are modifying the in-memory contents. */
@@ -2360,9 +2360,8 @@ elf64_hppa_finalize_dynreloc (dyn_h, dat
switch (rent->type)
{
case R_PARISC_FPTR64:
- /* Allocate one iff we are not building a shared library and
- !want_opd, which by this point will be true only if we're
- actually allocating one statically in the main executable. */
+ /* Allocate one iff we are building a shared library and don't
+ want an opd entry. */
if (!info->shared && dyn_h->want_opd)
continue;
break;
@@ -2395,7 +2394,7 @@ elf64_hppa_finalize_dynreloc (dyn_h, dat
We use a section symbol recorded by check_relocs as the
base symbol for the relocation. The addend is the difference
between the section symbol and the address of the .opd entry. */
- if (info->shared && rent->type == R_PARISC_FPTR64)
+ if (info->shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
{
bfd_vma value, value2;