This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug other/60465] Compiling glibc-2.17,2.18 with gcc-4.8.2 and binutils-2.23.2,2.24 results in segfaults in _start / elf_get_dynamic_info
- From: "devurandom at gmx dot net" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 18 Mar 2014 07:29:42 +0000
- Subject: [Bug other/60465] Compiling glibc-2.17,2.18 with gcc-4.8.2 and binutils-2.23.2,2.24 results in segfaults in _start / elf_get_dynamic_info
- Auto-submitted: auto-generated
- References: <bug-60465-4 at http dot gcc dot gnu dot org/bugzilla/>
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465
devurandom at gmx dot net changed:
What |Removed |Added
----------------------------------------------------------------------------
Target| |ia64-unknown-linux-gnu
Known to work| |4.7.3
Host| |ia64-unknown-linux-gnu
Known to fail| |4.8.2
Build| |ia64-unknown-linux-gnu
--- Comment #3 from devurandom at gmx dot net ---
Mike Frysinger 2014-03-18 07:17:05 UTC
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.