Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 17 Oct 2011 21:56:12 +0400
From: Vasiliy Kulikov <segoon@...nwall.com>
To: owl-dev@...ts.openwall.com
Subject: gcc 4.6.1: glibc __sincos() issue

Hi,

After building gcc 4.6.1 and making glibc compilable there is one error.
Groff's "pic" built with glibc built with gcc 4.6.1 calls __sincos and
goes into infinite __sincos recursion:

/usr/src/world/rpm-work-1/BUILD/groff-1.20.1/src/roff/groff/groff: pic: Signal 11
<standard input>:226: warning: closing delimiter does not match

It is "pic pic.ms" command.  If run it under gdb:

$ bash -c 'ulimit -s 50; gdb -d ~/sources/Owl/packages/glibc/glibc-2.3.6/conf/ ../src/preproc/pic/pic'

(gdb) run pic.ms
[...pic's output skipped...]
Program received signal SIGSEGV, Segmentation fault.
__sincos (x=1.5707963267948966, sinx=0x7fffae3f0048,
cosx=0x7fffae3f0040)
    at ../sysdeps/ieee754/dbl-64/s_sincos.c:32
32    GET_HIGH_WORD (ix, x);
(gdb) info stack
...
#20 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#21 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#22 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#23 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
...
#33463 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#33464 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#33465 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
#33466 0x0000000000410dc0 in object_spec::make_arc ()
#33467 0x0000000000000000 in ?? ()
#33468 0x00002b2974c7d5e0 in _IO_2_1_stderr_ () from /lib64/libc.so.6
#33469 0x0000000000637dc0 in current_position ()
#33470 0x3fe921fb54442d18 in ?? ()
#33471 0x0000000000000078 in ?? ()
#33472 0x0000000000000040 in ?? ()
#33473 0x4016000000000000 in ?? ()
#33474 0x0000000000000000 in ?? ()
#33475 0x4017000000000000 in ?? ()
#33476 0x3fd0000000000000 in ?? ()
#33477 0x0000000000000000 in ?? ()
#33478 0x0000000000000000 in ?? ()
#33479 0x3fc0000000000000 in ?? ()
#33480 0x3fc0000000000000 in ?? ()
#33481 0x0000000001d25360 in ?? ()
#33482 0x0000000001d25360 in ?? ()
#33483 0x0000000000000040 in ?? ()
#33484 0x0000000000411f45 in object_spec::make_linear ()
#33485 0x000000000000003b in ?? ()
#33486 0x000000000041caf7 in string::operator= ()
(gdb) frame 33000
#33000 0x00002b29744e182e in __sincos (x=Variable "x" is not available.) at ../sysdeps/ieee754/dbl-64/s_sincos.c:39
39        *sinx = *cosx = x - x;
(gdb) list
34    /* |x| ~< pi/4 */
35    ix &= 0x7fffffff;
36    if (ix>=0x7ff00000)
37      {
38        /* sin(Inf or NaN) is NaN */
39        *sinx = *cosx = x - x;
40      }
41    else
42      {
43        *sinx = sin (x);

(0x00002b29744e182e doesn't match line 39 of the source file, see below.)

(gdb) disassemble __sincos
Dump of assembler code for function __sincos:
0x00002b29744e17f0 <__sincos+0>:    mov    %rbx,0xfffffffffffffff0(%rsp)
0x00002b29744e17f5 <__sincos+5>:    mov    %rbp,0xfffffffffffffff8(%rsp)
0x00002b29744e17fa <__sincos+10>:   sub    $0x38,%rsp
0x00002b29744e17fe <__sincos+14>:   movsd  %xmm0,0x8(%rsp)
0x00002b29744e1804 <__sincos+20>:   mov    0x8(%rsp),%rax
0x00002b29744e1809 <__sincos+25>:   mov    %rdi,%rbp
0x00002b29744e180c <__sincos+28>:   mov    %rsi,%rbx
0x00002b29744e180f <__sincos+31>:   shr    $0x20,%rax
0x00002b29744e1813 <__sincos+35>:   and    $0x7fffffff,%eax
0x00002b29744e1818 <__sincos+40>:   cmp    $0x7fefffff,%eax
0x00002b29744e181d <__sincos+45>:   jg     0x2b29744e1850 <__sincos+96>
0x00002b29744e181f <__sincos+47>:   lea    0x10(%rsp),%rsi
0x00002b29744e1824 <__sincos+52>:   lea    0x18(%rsp),%rdi
0x00002b29744e1829 <__sincos+57>:   callq  0x2b29744bfcd0 <_init+40>
0x00002b29744e182e <__sincos+62>:   mov    0x18(%rsp),%rax <---------------ret address
0x00002b29744e1833 <__sincos+67>:   mov    %rax,0x0(%rbp)
0x00002b29744e1837 <__sincos+71>:   mov    0x10(%rsp),%rax
0x00002b29744e183c <__sincos+76>:   mov    0x30(%rsp),%rbp
0x00002b29744e1841 <__sincos+81>:   mov    %rax,(%rbx)
0x00002b29744e1844 <__sincos+84>:   mov    0x28(%rsp),%rbx
0x00002b29744e1849 <__sincos+89>:   add    $0x38,%rsp
0x00002b29744e184d <__sincos+93>:   retq   
0x00002b29744e184e <__sincos+94>:   data16
0x00002b29744e184f <__sincos+95>:   nop    
0x00002b29744e1850 <__sincos+96>:   subsd  %xmm0,%xmm0
0x00002b29744e1854 <__sincos+100>:  mov    0x28(%rsp),%rbx
0x00002b29744e1859 <__sincos+105>:  mov    0x30(%rsp),%rbp
0x00002b29744e185e <__sincos+110>:  movsd  %xmm0,(%rsi)
0x00002b29744e1862 <__sincos+114>:  movsd  %xmm0,(%rdi)
0x00002b29744e1866 <__sincos+118>:  add    $0x38,%rsp
0x00002b29744e186a <__sincos+122>:  retq   
End of assembler dump.
(gdb) x/i 0x2b29744bfcd0
0x2b29744bfcd0 <_init+40>:  jmpq   *2601770(%rip)        # 0x2b297473b000 <__JCR_LIST__+536>


callq at _init+40 is a call to __sincos().

In the source file (./sysdeps/ieee754/dbl-64/s_sincos.c):

    void
    __sincos (double x, double *sinx, double *cosx)
    {
      int32_t ix;

      /* High word of x. */
      GET_HIGH_WORD (ix, x);

      /* |x| ~< pi/4 */
      ix &= 0x7fffffff;
      if (ix>=0x7ff00000)
        {
          /* sin(Inf or NaN) is NaN */
          *sinx = *cosx = x - x;
        }
      else
        {
          *sinx = sin (x);
          *cosx = cos (x);
        }
    }
    weak_alias (__sincos, sincos)


So, it is an optimised call to sin() and cos(), which is optimised to
call to __sincos().  However, I cannot understand how it can happen as
sin() and cos() are defined in ./sysdeps/ieee754/dbl-64/s_sin.c as
following:

    double __cos(double x)
    {
      double y,xx,res,t,cor,s,c,sn,ssn,cs,ccs,xn,a,da,db,eps,xn1,xn2;
      mynumber u,v;
      int4 k,m,n;

      u.x = x;
      m = u.i[HIGH_HALF];
      k = 0x7fffffff&m;

      if (k < 0x3e400000 ) return 1.0; /* |x|<2^-27 => cos(x)=1 */

      else if (k < 0x3feb6000 ) {/* 2^-27 < |x| < 0.855469 */
        y=ABS(x);
        u.x = big.x+y;
        y = y-(u.x-big.x);
        xx=y*y;
        s = y + y*xx*(sn3 +xx*sn5);
        c = xx*(cs2 +xx*(cs4 + xx*cs6));
        k=u.i[LOW_HALF]<<2;
        sn=sincos.x[k];
        ssn=sincos.x[k+1];
        cs=sincos.x[k+2];
        ccs=sincos.x[k+3];
        cor=(ccs-s*ssn-cs*c)-sn*s;
        res=cs+cor;
        cor=(cs-res)+cor;
        return (res==res+1.020*cor)? res : cslow2(x);

    }    /*   else  if (k < 0x3feb6000)    */
    ...
      else return x / x; /* |x| > 2^1024 */
      return 0;

    }
    weak_alias (__cos, cos)

I see no call to __sincos() inside.


It is the used version of cos() as removing this weak_alias() makes
groff compilation fail with "undefined function: cos".


As removing the latter weak_alias() makes cos() invisible, I cannot
understand what makes __sincos() call itself.

Any ideas?

If it can help, I can post resulting libm/libc or .o files.

Thanks,

-- 
Vasiliy

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ