On Sun, May 02, 2010 at 11:38:39PM +0200, Gerald Pfeifer wrote:
> As http://gcc.gnu.org/ml/gcc-testresults/2010-05/msg00120.html shows,
> *-unknown-freebsd* exhibits tons of failures around LTO.
> 
> I dug a bit deeper, and even the most trivial test program
>   int main() { }
> fails with
>   lto1: internal compiler error: compressed stream: data error
>   Please submit a full bug report,
>   with preprocessed source if appropriate.
>   See <http://gcc.gnu.org/bugs.html> for instructions.
>   lto-wrapper: /files/pfeifer/gcc/bin/gcc returned 1 exit status
>   collect2: lto-wrapper returned 1 exit status
> when compiled with gcc -flto x.c.

Hi Gerald,

First sorry about the late reply.

The problem is indeed caused by a small incomptibility of FreeBSD
libelf with other libelf implementations.

The elf_getbase() API in FreeBSD libelf can only be called using
an archive member ELF descriptor. It will return -1 (indicates an error)
when called with a "regular" ELF object.

The lto_obj_build_section_table() function in lto-elf.c calls
elf_getbase() to get the offset base for a "regular" ELF object. On
FreeBSD it gets -1.  (Side notes: lto-elf.c should really check return
values of libelf APIs) And later it uses -1 as base_offset for all the
ELF sections thus results in an off-by-one error when passing the
section data to zlib to inflate.

Could you please try applying the attached patch to the libelf in
FreeBSD 7.3 and see if it fixes gcc4.6 lto?

Thanks,
Kai
diff -urN libelf.orig/elf_getbase.c libelf/elf_getbase.c
--- libelf.orig/elf_getbase.c	2010-05-20 18:49:43.000000000 +0200
+++ libelf/elf_getbase.c	2010-05-20 18:52:49.000000000 +0200
@@ -34,12 +34,14 @@
 off_t
 elf_getbase(Elf *e)
 {
-	if (e == NULL ||
-	    e->e_parent == NULL) {
+	if (e == NULL) {
 		LIBELF_SET_ERROR(ARGUMENT, 0);
 		return (off_t) -1;
 	}
 
-	return ((off_t) ((uintptr_t) e->e_rawfile -
-	    (uintptr_t) e->e_parent->e_rawfile));
+	if (e->e_parent)
+		return ((off_t) ((uintptr_t) e->e_rawfile -
+		    (uintptr_t) e->e_parent->e_rawfile));
+	else
+		return (off_t) 0;
 }

Reply via email to