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