call_init in libc6 2.3.6.ds1-11

"John David Anglin" <[email protected]>
Newsgroups gmane.linux.ports.hppa
Message-ID <[email protected]>
I had a segv in /bin/sh today:

Core was generated by `/bin/sh -c echo ../../../gcc/libjava/classpath/lib/java/awt/im/spi/*.class > ja'.
Program terminated with signal 11, Segmentation fault.
#0  0x4073b16c in init () from /lib/libc.so.6
(gdb) bt
#0  0x4073b16c in init () from /lib/libc.so.6
#1  0x400d77e8 in call_init () from /lib/ld.so.1
#2  0x400d77e8 in call_init () from /lib/ld.so.1
Previous frame identical to this frame (corrupt stack?)
(gdb) disass 0x4073b15c 0x4073b17c
Dump of assembler code from 0x4073b15c to 0x4073b17c:
0x4073b15c <_dl_start+12>:      stw r19,-20(sp)
0x4073b160 <_dl_start+16>:      nop
0x4073b164 <init+0>:    stw rp,-14(sp)
0x4073b168 <init+4>:    addil L%1000,r19,r1
0x4073b16c <init+8>:    ldw 450(r1),ret0
0x4073b170 <init+12>:   stw,ma r6,40(sp)
0x4073b174 <init+16>:   copy r24,r6
0x4073b178 <init+20>:   stw r5,-3c(sp)
End of assembler dump.
(gdb) p/x $r1
$1 = 0x40df352f
(gdb) p/x $r19
$2 = 0x40df252f

So, the problem is that r19 is corrupt when init is called.  Looking
at call_init, I see:

0x400d77ac <call_init+176>:     bb,<,n r20,1e,0x400d7884 <call_init+392>
0x400d77b0 <call_init+180>:     cmpib,=,n 0,r21,0x400d77ec <call_init+240>
0x400d77b4 <call_init+184>:     ldw 4(r21),r20
0x400d77b8 <call_init+188>:     ldw 0(r3),ret0
0x400d77bc <call_init+192>:     add,l ret0,r20,r22
0x400d77c0 <call_init+196>:     bb,>=,n r22,1e,0x400d7854 <call_init+344>
0x400d77c4 <call_init+200>:     copy r19,r4
0x400d77c8 <call_init+204>:     fstw fr14,-10(sp)
0x400d77cc <call_init+208>:     ldw -10(sp),r26
0x400d77d0 <call_init+212>:     fstw fr13,-10(sp)
0x400d77d4 <call_init+216>:     ldw -10(sp),r25
0x400d77d8 <call_init+220>:     fstw fr12,-10(sp)
0x400d77dc <call_init+224>:     ldw -10(sp),r24
0x400d77e0 <call_init+228>:     b,l 0x400dedd4 <$$dyncall>,r31
0x400d77e4 <call_init+232>:     copy r31,rp
0x400d77e8 <call_init+236>:     copy r4,r19

The address for the call to init is constructed by the loads at
0x400d77b4 and 0x400d77b8, followed by the add at 0x400d77bc:

gdb) p/x $r3
$8 = 0x400010b0
(gdb) x/x 0x400010b0
0x400010b0:     0x4071c000
(gdb) p/x $r21
$9 = 0x408621dc
(gdb) x/4x 0x408621dc
0x408621dc <.LC2+20>:   0x0000000c      0x0001f164      0x0000001a      0x001441e0
(gdb) p/x 0x4071c000 + 0x0001f164
$12 = 0x4073b164

So, init is being called directly.  This highly suspect for a call
in a shared library ($$dyncall won't setup r19).

I still don't completely understand what's happening here as r4 and
r19 don't appear to be consistent.  Here's the register dump:

Feb 17 11:58:01 localhost kernel: do_page_fault() pid=26501 command='sh' type=15 address=0x40df397f
Feb 17 11:58:01 localhost kernel: vm_start = 0x40868000, vm_end = 0x4086a000
Feb 17 11:58:01 localhost kernel:
Feb 17 11:58:01 localhost kernel:      YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI
Feb 17 11:58:01 localhost kernel: PSW: 00000000000001100000000100001111 Not tainted
Feb 17 11:58:01 localhost kernel: r00-03  000000000006010f 0000000040df352f 00000000400d77eb 00000000400010b0
Feb 17 11:58:01 localhost kernel: r04-07  00000000400f49b8 0000000000000002 0000000000000005 00000000400f5888
Feb 17 11:58:01 localhost kernel: r08-11  00000000400f5874 0000000000032000 0000000000033000 0000000000046ee8
Feb 17 11:58:01 localhost kernel: r12-15  0000000000000001 0000000000032000 0000000000046ee8 0000000000046ee8
Feb 17 11:58:01 localhost kernel: r16-19  0000000000000001 0000000000000000 0000000000046ee8 0000000040df252f
Feb 17 11:58:01 localhost kernel: r20-23  000000004086221c 00000000408621dc 000000004073b164 00000000c030e8bc
Feb 17 11:58:01 localhost kernel: r24-27  00000000c030e8bc 00000000c030e8ac 0000000000000003 00000000000d6d34
Feb 17 11:58:01 localhost kernel: r28-31  0000000040df252f 00000000000000d0 00000000c030ec80 00000000400d77eb
Feb 17 11:58:01 localhost kernel: sr00-03  0000000000e8c800 0000000000e8c800 0000000000000000 0000000000e8c800
Feb 17 11:58:01 localhost kernel: sr04-07  0000000000e8c800 0000000000e8c800 0000000000e8c800 0000000000e8c800

This would appear to have something to do with this define:

/* The test for "addr & 2" below is to accomodate old binaries which
   violated the ELF ABI by pointing DT_INIT and DT_FINI at a function
   descriptor.  */
#define DL_DT_INIT_ADDRESS(map, addr) \
  ((Elf32_Addr)(addr) & 2 ? (addr) : DL_AUTO_FUNCTION_ADDRESS (map, addr))

Dave
- 
J. David Anglin                                  [email protected]
National Research Council of Canada              (613) 990-0752 (FAX: 952-6602)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.