This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: PowerPC64 toc edit segfault
This fixes two segfaults in ppc64_elf_edit_toc, found when simply
running the binutils testsuite using an -mcmodel=medium ppc64
compiler. Embarrassing. My binutils testsuite runs weren't using a
new bleeding edge compiler as I thought, but the old 4.4.1 system
compiler.
Also fixes a number of ld tests that fail/xpass with a new ppc64 gcc.
I'm disabling the non-PIC visibility tests entirely for
powerpc*-linux. See the comment for why.
Applied mainline and 2.21 branch.
bfd/
* elf64-ppc.c (ppc64_elf_edit_toc): Don't free toc relocs until
we are done. When optimising large toc, check that a global
symbol on a toc reloc is defined in a kept section.
ld/testsuite/
* ld-elfvsb/elfvsb.exp: Don't run any non-PIC tests on powerpc*-linux.
* ld-gc/gc.exp: Ensure powerpc64 test continues to fail.
* ld-srec/srec.exp: Don't edit toc on powerpc64.
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.341
diff -u -p -r1.341 elf64-ppc.c
--- bfd/elf64-ppc.c 8 Feb 2011 02:54:42 -0000 1.341
+++ bfd/elf64-ppc.c 9 Feb 2011 06:52:20 -0000
@@ -7907,7 +7908,7 @@ ppc64_elf_edit_toc (struct bfd_link_info
asection *toc, *sec;
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *local_syms;
- Elf_Internal_Rela *relstart, *rel;
+ Elf_Internal_Rela *relstart, *rel, *toc_relocs;
unsigned long *skip, *drop;
unsigned char *used;
unsigned char *keep, last, some_unused;
@@ -7922,6 +7923,7 @@ ppc64_elf_edit_toc (struct bfd_link_info
|| elf_discarded_section (toc))
continue;
+ toc_relocs = NULL;
local_syms = NULL;
symtab_hdr = &elf_symtab_hdr (ibfd);
@@ -8017,12 +8019,12 @@ ppc64_elf_edit_toc (struct bfd_link_info
&& toc->reloc_count != 0)
{
/* Read toc relocs. */
- relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
- info->keep_memory);
- if (relstart == NULL)
+ toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
+ info->keep_memory);
+ if (toc_relocs == NULL)
goto error_ret;
- for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
+ for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
{
enum elf_ppc64_reloc_type r_type;
unsigned long r_symndx;
@@ -8040,6 +8042,10 @@ ppc64_elf_edit_toc (struct bfd_link_info
r_symndx, ibfd))
goto error_ret;
+ if (sym_sec == NULL
+ || elf_discarded_section (sym_sec))
+ continue;
+
if (!SYMBOL_CALLS_LOCAL (info, h))
continue;
@@ -8078,11 +8084,8 @@ ppc64_elf_edit_toc (struct bfd_link_info
}
skip[rel->r_offset >> 3]
- |= can_optimize | ((rel - relstart) << 2);
+ |= can_optimize | ((rel - toc_relocs) << 2);
}
-
- if (elf_section_data (toc)->relocs != relstart)
- free (relstart);
}
if (skip == NULL)
@@ -8099,6 +8102,9 @@ ppc64_elf_edit_toc (struct bfd_link_info
&& relstart != NULL
&& elf_section_data (sec)->relocs != relstart)
free (relstart);
+ if (toc_relocs != NULL
+ && elf_section_data (toc)->relocs != toc_relocs)
+ free (toc_relocs);
if (skip != NULL)
free (skip);
return FALSE;
@@ -8338,7 +8344,7 @@ ppc64_elf_edit_toc (struct bfd_link_info
else if ((skip[val >> 3] & can_optimize) != 0)
{
Elf_Internal_Rela *tocrel
- = elf_section_data (toc)->relocs + (skip[val >> 3] >> 2);
+ = toc_relocs + (skip[val >> 3] >> 2);
unsigned long tsym = ELF64_R_SYM (tocrel->r_info);
switch (r_type)
@@ -8418,15 +8424,9 @@ ppc64_elf_edit_toc (struct bfd_link_info
Elf_Internal_Rela *wrel;
bfd_size_type sz;
- /* Read toc relocs. */
- relstart = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
- TRUE);
- if (relstart == NULL)
- goto error_ret;
-
/* Remove unused toc relocs, and adjust those we keep. */
- wrel = relstart;
- for (rel = relstart; rel < relstart + toc->reloc_count; ++rel)
+ wrel = toc_relocs;
+ for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
if ((skip[rel->r_offset >> 3]
& (ref_from_discarded | can_optimize)) == 0)
{
@@ -8439,12 +8439,15 @@ ppc64_elf_edit_toc (struct bfd_link_info
&local_syms, NULL, NULL))
goto error_ret;
- toc->reloc_count = wrel - relstart;
+ elf_section_data (toc)->relocs = toc_relocs;
+ toc->reloc_count = wrel - toc_relocs;
rel_hdr = _bfd_elf_single_rel_hdr (toc);
sz = rel_hdr->sh_entsize;
rel_hdr->sh_size = toc->reloc_count * sz;
}
}
+ else if (elf_section_data (toc)->relocs != toc_relocs)
+ free (toc_relocs);
if (local_syms != NULL
&& symtab_hdr->contents != (unsigned char *) local_syms)
Index: ld/testsuite/ld-elfvsb/elfvsb.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-elfvsb/elfvsb.exp,v
retrieving revision 1.34
diff -u -p -r1.34 elfvsb.exp
--- ld/testsuite/ld-elfvsb/elfvsb.exp 8 Nov 2010 06:43:37 -0000 1.34
+++ ld/testsuite/ld-elfvsb/elfvsb.exp 9 Feb 2011 07:54:30 -0000
@@ -249,6 +249,14 @@ proc visibility_run {visibility} {
set VSBCFLAG ""
}}}}}}}}}
+ if { [istarget powerpc*-*-linux*] } {
+ # Testing non-PIC libraries is a waste of effort on any target.
+ # If you don't pass -fpic or -fPIC to gcc, gcc will assume quite
+ # reasonably that you are not compiling for a shared library.
+ # It can then make optimisations that result in shared library
+ # functions and variables not being overridable. Newer versions
+ # of gcc are more likely to do this.
+ } else {
# Compile the main program.
if ![ld_compile "$CC -g $CFLAGS $SHCFLAG $VSBCFLAG" $srcdir/$subdir/main.c $tmpdir/mainnp.o] {
unresolved "visibility ($visibility) (non PIC)"
@@ -369,8 +377,11 @@ proc visibility_run {visibility} {
visibility_test $visibility vp "visibility ($visibility)" mainnp.o sh1p.o sh2p.o elfvsb
} }
}
- }
+ }}
+ if { [istarget powerpc*-*-linux*] } {
+ # Don't bother.
+ } else {
# Now do the same tests again, but this time compile main.c PIC.
if ![ld_compile "$CC -g $CFLAGS $SHCFLAG $VSBCFLAG -DSHARED $picflag" $srcdir/$subdir/main.c $tmpdir/mainp.o] {
unresolved "visibility ($visibility) (PIC main, non PIC so)"
@@ -433,7 +444,7 @@ proc visibility_run {visibility} {
} else {
unresolved "visibility ($visibility) (PIC main)"
}
- }
+ }}
}
if [istarget mips*-*-*] {
Index: ld/testsuite/ld-gc/gc.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-gc/gc.exp,v
retrieving revision 1.10
diff -u -p -r1.10 gc.exp
--- ld/testsuite/ld-gc/gc.exp 8 Nov 2010 06:43:37 -0000 1.10
+++ ld/testsuite/ld-gc/gc.exp 9 Feb 2011 07:54:30 -0000
@@ -27,6 +27,11 @@ if ![check_gc_sections_available] {
set cflags "-ffunction-sections -fdata-sections"
set objfile "tmpdir/gc.o"
+if [istarget powerpc64*-*-*] {
+ # otherwise with -mcmodel=medium gcc we get XPASSes.
+ set cflags "$cflags -mminimal-toc"
+}
+
if { [is_remote host] || [which $CC] != 0 } {
ld_compile "$CC -c $CFLAGS $cflags" $srcdir/$subdir/gc.c $objfile
}
Index: ld/testsuite/ld-srec/srec.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-srec/srec.exp,v
retrieving revision 1.33
diff -u -p -r1.33 srec.exp
--- ld/testsuite/ld-srec/srec.exp 1 Oct 2009 23:29:28 -0000 1.33
+++ ld/testsuite/ld-srec/srec.exp 9 Feb 2011 07:54:31 -0000
@@ -271,6 +271,10 @@ proc run_srec_test { test objs } {
set flags "$flags -no-relax"
}
+ if [istarget powerpc64*-*-*] {
+ set flags "$flags --no-toc-optimize"
+ }
+
if { ![ld_simple_link $ld tmpdir/sr1 "$flags $objs"] \
|| ![ld_simple_link $ld tmpdir/sr2.sr "$flags --oformat srec $objs"] } {
fail $test
--
Alan Modra
Australia Development Lab, IBM