* PowerPC64 toc edit segfault
@ 2011-02-08 3:02 Alan Modra
2011-02-09 8:20 ` Alan Modra
0 siblings, 1 reply; 3+ messages in thread
From: Alan Modra @ 2011-02-08 3:02 UTC (permalink / raw)
To: binutils
This fixes an oversight in the PowerPC64 linker TOC editing code, that
can lead to a segfault. An input object file may have a non-empty
.toc section but no references to the .toc entries. Odd, but possible.
Most likely with user assembly, but might also occur due to compiler
bugs.
Applied mainline and branch.
* elf64-ppc.c (ppc64_elf_edit_toc): Don't segfault on NULL
local_syms when looking for local symbols in .toc.
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.340
diff -u -p -r1.340 elf64-ppc.c
--- bfd/elf64-ppc.c 31 Jan 2011 22:38:26 -0000 1.340
+++ bfd/elf64-ppc.c 8 Feb 2011 01:33:46 -0000
@@ -8372,34 +8372,35 @@ ppc64_elf_edit_toc (struct bfd_link_info
/* We shouldn't have local or global symbols defined in the TOC,
but handle them anyway. */
- for (sym = local_syms;
- sym < local_syms + symtab_hdr->sh_info;
- ++sym)
- if (sym->st_value != 0
- && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc)
- {
- unsigned long i;
+ if (local_syms != NULL)
+ for (sym = local_syms;
+ sym < local_syms + symtab_hdr->sh_info;
+ ++sym)
+ if (sym->st_value != 0
+ && bfd_section_from_elf_index (ibfd, sym->st_shndx) == toc)
+ {
+ unsigned long i;
- if (sym->st_value > toc->rawsize)
- i = toc->rawsize >> 3;
- else
- i = sym->st_value >> 3;
+ if (sym->st_value > toc->rawsize)
+ i = toc->rawsize >> 3;
+ else
+ i = sym->st_value >> 3;
- if ((skip[i] & (ref_from_discarded | can_optimize)) != 0)
- {
- if (local_toc_syms)
- (*_bfd_error_handler)
- (_("%s defined on removed toc entry"),
- bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL));
- do
- ++i;
- while ((skip[i] & (ref_from_discarded | can_optimize)));
- sym->st_value = (bfd_vma) i << 3;
- }
+ if ((skip[i] & (ref_from_discarded | can_optimize)) != 0)
+ {
+ if (local_toc_syms)
+ (*_bfd_error_handler)
+ (_("%s defined on removed toc entry"),
+ bfd_elf_sym_name (ibfd, symtab_hdr, sym, NULL));
+ do
+ ++i;
+ while ((skip[i] & (ref_from_discarded | can_optimize)));
+ sym->st_value = (bfd_vma) i << 3;
+ }
- sym->st_value -= skip[i];
- symtab_hdr->contents = (unsigned char *) local_syms;
- }
+ sym->st_value -= skip[i];
+ symtab_hdr->contents = (unsigned char *) local_syms;
+ }
/* Adjust any global syms defined in this toc input section. */
if (toc_inf.global_toc_syms)
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: PowerPC64 toc edit segfault
2011-02-08 3:02 PowerPC64 toc edit segfault Alan Modra
@ 2011-02-09 8:20 ` Alan Modra
2011-02-15 4:00 ` Alan Modra
0 siblings, 1 reply; 3+ messages in thread
From: Alan Modra @ 2011-02-09 8:20 UTC (permalink / raw)
To: binutils
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
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: PowerPC64 toc edit segfault
2011-02-09 8:20 ` Alan Modra
@ 2011-02-15 4:00 ` Alan Modra
0 siblings, 0 replies; 3+ messages in thread
From: Alan Modra @ 2011-02-15 4:00 UTC (permalink / raw)
To: binutils
On Wed, Feb 09, 2011 at 06:50:28PM +1030, Alan Modra wrote:
> This fixes two segfaults in ppc64_elf_edit_toc, found when simply
> @@ -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)
> {
Blah. Removing the above "Read toc relocs" caused a segfault when
linking -mcmodel=small code.
* elf64-ppc.c (ppc64_elf_edit_toc): Reinstate second read of
toc relocs. Fuss over free(NULL).
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.342
diff -u -p -r1.342 elf64-ppc.c
--- bfd/elf64-ppc.c 9 Feb 2011 08:16:00 -0000 1.342
+++ bfd/elf64-ppc.c 15 Feb 2011 03:54:10 -0000
@@ -8424,6 +8424,12 @@ ppc64_elf_edit_toc (struct bfd_link_info
bfd_size_type sz;
/* Remove unused toc relocs, and adjust those we keep. */
+ if (toc_relocs == NULL)
+ toc_relocs = _bfd_elf_link_read_relocs (ibfd, toc, NULL, NULL,
+ info->keep_memory);
+ if (toc_relocs == NULL)
+ goto error_ret;
+
wrel = toc_relocs;
for (rel = toc_relocs; rel < toc_relocs + toc->reloc_count; ++rel)
if ((skip[rel->r_offset >> 3]
@@ -8445,7 +8451,8 @@ ppc64_elf_edit_toc (struct bfd_link_info
rel_hdr->sh_size = toc->reloc_count * sz;
}
}
- else if (elf_section_data (toc)->relocs != toc_relocs)
+ else if (toc_relocs != NULL
+ && elf_section_data (toc)->relocs != toc_relocs)
free (toc_relocs);
if (local_syms != NULL
--
Alan Modra
Australia Development Lab, IBM
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-02-15 4:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-08 3:02 PowerPC64 toc edit segfault Alan Modra
2011-02-09 8:20 ` Alan Modra
2011-02-15 4:00 ` Alan Modra
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).