http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60558
Bug ID: 60558 Summary: building glibc-2.19 w/gcc-4.8.x on ia64 produces bad ld.so Product: gcc Version: 4.8.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target Assignee: unassigned at gcc dot gnu.org Reporter: vapier at gentoo dot org CC: toolchain at gentoo dot org Host: ia64-linux-gnu Target: ia64-linux-gnu Build: ia64-linux-gnu if you build current master glibc w/gcc-4.8.2 & binutils-2.23.2 like so: ../configure --prefix=/usr libc_cv_ehdr_start=no make -j4 then try to run a simple app like so: echo 'main(){puts("HI");}' | gcc -x c - -o a.out ./elf/ld.so --library-path $PWD ./a.out it crashes like so: Segmentation fault (core dumped) i suspect bad code generation because: - recompiling only elf/rtld.c w/gcc-4.7.3 produces a working build - the C code looks correct (via poking; see below) - tweaking the code slightly produces a working build w/4.8: - else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) - info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; + { + size_t i = DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM + + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM; + info[i] = dyn; + } throwing it into a debugger shows: $ gdb --args ./elf/ld.so --library-path $PWD ./a.out Reading symbols from /home/vapier/glibc/build/elf/ld.so...done. (gdb) run Starting program: /home/vapier/glibc/build/./elf/ld.so --library-path /home/vapier/glibc/build ./a.out Program received signal SIGSEGV, Segmentation fault. 0x200000080000b010 in elf_get_dynamic_info (temp=0x0, l=0x2000000800051b08 <_rtld_local+2456>) at get-dynamic-info.h:61 61 + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; (gdb) list 56 else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM) 57 info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM 58 + DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn; 59 else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM) 60 info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM 61 + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; 62 ++dyn; 63 } 64 65 #define DL_RO_DYN_TEMP_CNT 8 the info pointer is sane: (gdb) p &_rtld_global._dl_rtld_map.l_info $1 = (Elf64_Dyn *(*)[77]) 0x20000008000515d8 <_rtld_local+2520> (gdb) print info $2 = (Elf64_Dyn **) 0x20000008000515d8 <_rtld_local+2520> as is the dyn tag: (gdb) print dyn $3 = (Elf64_Dyn *) 0x200000080004c8d8 (gdb) print *dyn $4 = { d_tag = 0x6ffffef5, d_un = { d_val = 0x2d8, d_ptr = 0x2d8 } } that calculated offset is 0x4c and the link map is big enough to hold it: (gdb) print sizeof(_rtld_local._dl_rtld_map.l_info) / sizeof(_rtld_local._dl_rtld_map.l_info[0]) $5 = 0x4d but the assembly is clearly wrong: (gdb) display/i $pc 1: x/i $pc => 0x200000080000b271 <_dl_start+2737>: (p07) st8 [r14]=r15 (gdb) p $r15 $6 = 0x200000080004c8d8 (gdb) p $r14 $7 = 0x51838 $r15 is set to the right value (dyn), but r14 is now incomplete. stepping through the previous ~20 insns shows that the right value doesn't get near $r14 ... but my ia64 asm skills are not great, so i could be missing something.