This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PATCH: PR ld/5789: Linker doesn't check weak and hidden symbols
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: binutils at sourceware dot org
- Date: Mon, 3 Mar 2008 08:47:05 +1030
- Subject: Re: PATCH: PR ld/5789: Linker doesn't check weak and hidden symbols
- References: <20080224001111.GA5967@lucon.org> <20080228083528.GA25964@bubble.grove.modra.org> <6dc9ffc80802280702i1d8949e1y134a73740726125a@mail.gmail.com> <20080228233328.GB26067@bubble.grove.modra.org> <6dc9ffc80802291505l32f5fabfo972cdb8c09c8a6fc@mail.gmail.com>
On Fri, Feb 29, 2008 at 03:05:14PM -0800, H.J. Lu wrote:
> On Thu, Feb 28, 2008 at 3:33 PM, Alan Modra <amodra@bigpond.net.au> wrote:
> > I see these on powerpc-linux with gcc-3.4.5
> > FAIL: visibility (hidden_undef) (non PIC)
> > FAIL: visibility (hidden_undef) (non PIC, load offset)
> > FAIL: visibility (hidden_undef) (PIC main, non PIC so)
> >
>
> The expected linker behavior for those 3 tests is linker error
> for hidden undefined symbols.
Doh! If I'd checked elfvsb.exp I'd have seen this myself.
powerpc-linux was failing simply because relocate_section was bailing
out early and thus not reporting all the undefined symbol errors.
That particular problem is fixed by the last hunk below.
* elf32-ppc.c (allocate_dynrelocs): Discard relocs on
undefined symbols with internal or hidden visibility.
(ppc_elf_relocate_section): Likewise. Use SYMBOL_CALLS_LOCAL
rather than SYMBOL_REFERENCES_LOCAL on branches. Don't
return immediately on dynamic reloc error.
HJ, Please commit your _bfd_elf_symbol_refs_local_p fix.
Index: bfd/elf32-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-ppc.c,v
retrieving revision 1.233
diff -u -p -r1.233 elf32-ppc.c
--- bfd/elf32-ppc.c 1 Mar 2008 06:52:32 -0000 1.233
+++ bfd/elf32-ppc.c 2 Mar 2008 22:04:25 -0000
@@ -4811,6 +4811,13 @@ allocate_dynrelocs (struct elf_link_hash
}
}
+ /* Discard relocs on undefined symbols that must be local. */
+ if (eh->dyn_relocs != NULL
+ && h->root.type == bfd_link_hash_undefined
+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+ eh->dyn_relocs = NULL;
+
/* Also discard relocs on undefined weak syms with non-default
visibility. */
if (eh->dyn_relocs != NULL
@@ -6440,7 +6447,7 @@ ppc_elf_relocate_section (bfd *output_bf
case R_PPC_REL14_BRNTAKEN:
/* If these relocations are not to a named symbol, they can be
handled right here, no need to bother the dynamic linker. */
- if (SYMBOL_REFERENCES_LOCAL (info, h)
+ if (SYMBOL_CALLS_LOCAL (info, h)
|| h == htab->elf.hgot)
break;
/* fall through */
@@ -6458,9 +6465,12 @@ ppc_elf_relocate_section (bfd *output_bf
break;
if ((info->shared
- && (h == NULL
- || ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
- || h->root.type != bfd_link_hash_undefweak)
+ && !(h != NULL
+ && ((h->root.type == bfd_link_hash_undefined
+ && (ELF_ST_VISIBILITY (h->other) == STV_HIDDEN
+ || ELF_ST_VISIBILITY (h->other) == STV_INTERNAL))
+ || (h->root.type == bfd_link_hash_undefweak
+ && ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)))
&& (MUST_BE_DYN_RELOC (r_type)
|| !SYMBOL_CALLS_LOCAL (info, h)))
|| (ELIMINATE_COPY_RELOCS
@@ -6503,7 +6513,6 @@ ppc_elf_relocate_section (bfd *output_bf
}
skip = 0;
-
outrel.r_offset =
_bfd_elf_section_offset (output_bfd, info, input_section,
rel->r_offset);
@@ -6515,7 +6524,10 @@ ppc_elf_relocate_section (bfd *output_bf
if (skip)
memset (&outrel, 0, sizeof outrel);
- else if (!SYMBOL_REFERENCES_LOCAL (info, h))
+ else if ((h != NULL
+ && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak))
+ || !SYMBOL_REFERENCES_LOCAL (info, h))
{
unresolved_reloc = FALSE;
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
@@ -6529,14 +6541,14 @@ ppc_elf_relocate_section (bfd *output_bf
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
else
{
- long indx;
+ long indx = 0;
if (bfd_is_abs_section (sec))
- indx = 0;
+ ;
else if (sec == NULL || sec->owner == NULL)
{
bfd_set_error (bfd_error_bad_value);
- return FALSE;
+ ret = FALSE;
}
else
{
--
Alan Modra
Australia Development Lab, IBM