[uClibc] GCC-4.1.0 size optimization bug for MIPS architecture...

Steven J. Hill sjhill at realitydiluted.com
Wed Jun 29 04:59:15 UTC 2005


Greetings.

I have discovered what appears to be an optimization bug with '-Os'
in GCC-4.1.0 for the MIPS architecture. It appears that functions
which are declared as 'inline' are being ignored and instead turned
into to function calls which is breaking the dynamic linker loader
for uClibc on MIPS. I apologize for not being able to provide a
simpler test case, but I did my best to isolate the issue. I have
placed a tarball at:

http://www.realitydiluted.com/nptl-uclibc/gcc-4.1.0-size-optimization-error.tar.bz2 


that contains the source as well as the object files and final
loader binary for both the '-O1' and '-Os' cases. Hopefully that
will aide in discovering the problem.

First, compiling with '-O1' WORKS. My toolchain is binutils-2.16.1,
latest GCC-4.1.0 from head of CVS and latest snapshot of uClibc.
Compiling the loader with '-Os' results in a dynamic linker that
immediately segfaults.

Two isolated cases appear with the inlined functions on lines 179
and 193 of the 'dl-startup.c' file below.

    167		/* Check the ELF header to make sure everything looks ok.  */
    168		if (!header || header->e_ident[EI_CLASS] != ELFCLASS32 ||
    169				header->e_ident[EI_VERSION] != EV_CURRENT
    170				/* Do not use an inline _dl_strncmp here or some arches
    171				* will blow chunks, i.e. those that need to relocate all
    172				* string constants... */
    173				|| header->e_ident[EI_MAG0] != ELFMAG0
    174				|| header->e_ident[EI_MAG1] != ELFMAG1
    175				|| header->e_ident[EI_MAG2] != ELFMAG2
    176				|| header->e_ident[EI_MAG3] != ELFMAG3)
    177		{
    178			SEND_STDERR("Invalid ELF header\n");
** 179			_dl_exit(0);
    180		}
    181		SEND_STDERR_DEBUG("ELF header=");
    182		SEND_ADDRESS_STDERR_DEBUG(load_addr, 1);
    183	
    184	
    185		/* Locate the global offset table.  Since this code must be PIC
    186		 * we can take advantage of the magic offset register, if we
    187		 * happen to know what that is for this architecture.  If not,
    188		 * we can always read stuff out of the ELF file to find it... */
    189		got = elf_machine_dynamic();
    190		dpnt = (Elf32_Dyn *) (got + load_addr);
    191		SEND_STDERR_DEBUG("First Dynamic section entry=");
    192		SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
** 193		_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
    194		tpnt->loadaddr = load_addr;

In the '-O1' case, the functions are inlined as expected and the dynamic
linker functions as expected. When compiled with '-Os', the functions
are not inlined. Instead, they become normal function calls. Below is a 
snippet of the dissassembly with astericks (*) beside the function
calls.

...
			header->e_ident[EI_VERSION] != EV_CURRENT
			/* Do not use an inline _dl_strncmp here or some arches
			* will blow chunks, i.e. those that need to relocate all
			* string constants... */
			|| header->e_ident[EI_MAG0] != ELFMAG0
			|| header->e_ident[EI_MAG1] != ELFMAG1
			|| header->e_ident[EI_MAG2] != ELFMAG2
			|| header->e_ident[EI_MAG3] != ELFMAG3)
	{
		SEND_STDERR("Invalid ELF header\n");
		_dl_exit(0);
     5214:	8f998018 	lw	t9,-32744(gp)
     5218:	27390e20 	addiu	t9,t9,3616
*** 521c:	0320f809 	jalr	t9
     5220:	00002021 	move	a0,zero
     5224:	8fbc0018 	lw	gp,24(sp)
	}
	SEND_STDERR_DEBUG("ELF header=");
	SEND_ADDRESS_STDERR_DEBUG(load_addr, 1);


	/* Locate the global offset table.  Since this code must be PIC
	 * we can take advantage of the magic offset register, if we
	 * happen to know what that is for this architecture.  If not,
	 * we can always read stuff out of the ELF file to find it... */
	got = elf_machine_dynamic();
	dpnt = (Elf32_Dyn *) (got + load_addr);
	SEND_STDERR_DEBUG("First Dynamic section entry=");
	SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
	_dl_memset(tpnt, 0, sizeof(struct elf_resolve));
     5228:	8f998018 	lw	t9,-32744(gp)
     522c:	8f828010 	lw	v0,-32752(gp)
     5230:	27b00098 	addiu	s0,sp,152
     5234:	02002021 	move	a0,s0
     5238:	00002821 	move	a1,zero
     523c:	240600e4 	li	a2,228
     5240:	27391194 	addiu	t9,t9,4500
*** 5244:	0320f809 	jalr	t9
     5248:	00528821 	addu	s1,v0,s2
     524c:	3c037000 	lui	v1,0x7000
...

The segfault occurs immediately after 0x5244 due to an invalid value
being stored in t9. This appears to occur because of the gp being
written with a bogus value at 0x5224. Does anyone have some insight
into what is going on that is causing this erroneous behavior? Thanks.

-Steve



More information about the uClibc mailing list