Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

inline-optimized program crashes inside libstdc++ #3521

Closed Quuxplusone closed 14 years ago

Quuxplusone commented 14 years ago
Bugzilla Link PR6251
Status RESOLVED FIXED
Importance P normal
Reported by Ivan Sorokin (vanyacpp@gmail.com)
Reported on 2010-02-06 06:46:53 -0800
Last modified on 2010-03-29 14:49:33 -0700
Version trunk
Hardware PC Linux
CC andersca@icloud.com, anton@korobeynikov.info, edwin+bugs@etorok.eu, gonsolo@gmail.com, llvm-bugs@lists.llvm.org, m@fritschy.de, rjmccall@apple.com
Fixed by commit(s)
Attachments 13.cpp (570 bytes, text/plain)
before.s (22817 bytes, text/plain)
after.s (23406 bytes, text/plain)
before.s (20328 bytes, text/plain)
after.s (20921 bytes, text/plain)
testcase.cc (246 bytes, text/x-c++src)
testcase.cc (101 bytes, text/x-c++src)
bugpoint-reduced-simplified.ll (42654 bytes, application/octet-stream)
Blocks PR6023, PR6266
Blocked by
See also
The following program (see attachment) crashes when it is compiled with -O2.

ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -ggdb 13.cpp
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -O2 -ggdb 13.cpp
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gdb a.out
(gdb) run
Starting program: /home/ivan/d/llvm-build/Debug/bin/a.out

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff733f719 in free () from /lib/libc.so.6
(gdb) backtrace
#0  0x00007ffff733f719 in free () from /lib/libc.so.6
#1  0x00007ffff7b3656f in std::ios_base::~ios_base() () from
/usr/lib/libstdc++.so.6
#2  0x0000000000400eef in main () at 13.cpp:30

If I remove inheritance from fake_base or
If I remove fake_member member or
If I compile without -O2
the program doesn't crash.

Ubuntu 9.10 x86-64.

This bug occur when using boost::format.

I continue my experiments to make more precise bug report.
Quuxplusone commented 14 years ago

Attached 13.cpp (570 bytes, text/plain): 13.cpp

Quuxplusone commented 14 years ago
As I find out the program crashes dues to -inline optimization.

ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./opt -inline -S -o after.s before.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./llc before.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gcc -lstdc++ before.s.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./llc after.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gcc -lstdc++ after.s.s
ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
Segmentation fault
Quuxplusone commented 14 years ago

Attached before.s (22817 bytes, text/plain): before.s

Quuxplusone commented 14 years ago

Attached before.s (20328 bytes, text/plain): before.s

Quuxplusone commented 14 years ago

Attached after.s (23406 bytes, text/plain): after.s

Quuxplusone commented 14 years ago

Attached after.s (20921 bytes, text/plain): after.s

Quuxplusone commented 14 years ago

I've attached more simple example compiled with -fno-rtti and -fno-exceptions.

Quuxplusone commented 14 years ago

I've made an attempt to imitate external functions from libstdc++ to trace every external call and its arguments. To find out the difference between program before and after inliner. But I've failed to do this: the resulting program crashes and I don't understand why.

Do you have any suggestions how to find out what happened within inliner?

Is it possible to inline functions step by step? If it is, I can run program after every inlined function and check whether it works or not.

Quuxplusone commented 14 years ago

This is related to vbase initialization, I'll have a look at this.

Quuxplusone commented 14 years ago

Do you have any progress with bug? Is it bug in inliner? Will it be fixed before 2.7 release?

Quuxplusone commented 14 years ago
(In reply to comment #0)
> The following program (see attachment) crashes when it is compiled with -O2.
>
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -ggdb 13.cpp
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./a.out
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ ./clang++ -O2 -ggdb 13.cpp
> ivan@ivan-desktop:~/d/llvm-build/Debug/bin$ gdb a.out
> (gdb) run
> Starting program: /home/ivan/d/llvm-build/Debug/bin/a.out
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007ffff733f719 in free () from /lib/libc.so.6
> (gdb) backtrace
> #0  0x00007ffff733f719 in free () from /lib/libc.so.6
> #1  0x00007ffff7b3656f in std::ios_base::~ios_base() () from
> /usr/lib/libstdc++.so.6
> #2  0x0000000000400eef in main () at 13.cpp:30
>
> If I remove inheritance from fake_base or
> If I remove fake_member member or
> If I compile without -O2
> the program doesn't crash.
>
> Ubuntu 9.10 x86-64.
>
> This bug occur when using boost::format.
>
> I continue my experiments to make more precise bug report.
>
Quuxplusone commented 14 years ago
Yeah right, sorry, I don't like firefox.

Can reproduce this, happens only on implicit dtor call (i.e. new/delete the
streamstuff and it does work (for me)).

Cheers anyway.
Marcus
Quuxplusone commented 14 years ago

_Bug 6526 has been marked as a duplicate of this bug._

Quuxplusone commented 14 years ago

Attached testcase.cc (246 bytes, text/x-c++src): Testcase from duplicate bug entry

Quuxplusone commented 14 years ago

Attached testcase.cc (101 bytes, text/x-c++src): Reduced testcase

Quuxplusone commented 14 years ago
I happens with

#include <sstream>

int main()
{
    std::stringstream a;
    std::stringstream b;
}

but not with

#include <sstream>

int main()
{
    std::istringstream a;
    std::istringstream b;
}

or

#include <sstream>

int main()
{
    std::ostringstream a;
    std::ostringstream b;
}
Quuxplusone commented 14 years ago
Reduced testcase:

#include <istream>

int main()
{
    std::basic_iostream<char> a;
    std::basic_iostream<char> b;
}

It seems to have something to do with multiple inheritance.
Quuxplusone commented 14 years ago
Compiling

#include <ios>

template<typename _CharT>
class D : public std::ios_base
{};

template<typename _CharT>
class A : virtual public D<_CharT>
{};

template<typename _CharT>
class B : virtual public D<_CharT>
{
};

template<typename _CharT>
class C :       public A <_CharT>,
            public B<_CharT>
{
};

int main()
{
    C<char> a;
}

with clang++ -o bla bla.cc

fails with:

clang++  -o bla bla.cc
/tmp/cc-Rdw9GJ.o:(.rodata+0x54): undefined reference to `virtual thunk to
B<char>::~B()'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Quuxplusone commented 14 years ago
Further reduced:

class E
{
  public:
    struct _Words {};
    _Words      _M_word_zero;

    virtual ~E() {}
};

template<typename _CharT>
class D : public E
{};

template<typename _CharT>
class A : virtual public D<_CharT>
{};

template<typename _CharT>
class B : virtual public D<_CharT>
{
};

template<typename _CharT>
class C :       public A <_CharT>,
            public B<_CharT>
{
};

int main()
{
    C<char> a;
}

fails with:

/tmp/cc-5LKulY.o:(.rodata+0x54): undefined reference to `virtual thunk to
B<char>::~B()'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Quuxplusone commented 14 years ago
Reduced again:

class D {
        public:
                char c;
                virtual ~D() {}
};
class A : virtual public D {};
class B : virtual public D {};
class C : public A, public B {};

int main()
{
        C a;
}
Quuxplusone commented 14 years ago
Difference between g++ and clang++ generated .o files:

g++:
00000000 W _ZTv0_n12_N1BD0Ev
00000000 W _ZTv0_n12_N1BD1Ev

clang++:
         U _ZTv0_n12_N1BD0Ev
00000000 W _ZTv0_n12_N1BD1Ev

It seems that one thunk is not generated.
Quuxplusone commented 14 years ago
Similarily:

struct A {
    virtual void f();
};

int main()
{
    A a;
}

gives:

/tmp/cc-tBz301.o: In function `A::A()':
a.cc:(.gnu.linkonce.t._ZN1AC2Ev+0x11): undefined reference to `vtable for A'
collect2: ld returned 1 exit status
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Shouldn't the error message be something like:
"warning: Unimplemented virtual method" and no error, since constructing should
work?
Quuxplusone commented 14 years ago
(In reply to comment #22)
> Shouldn't the error message be something like:
> "warning: Unimplemented virtual method" and no error, since constructing
should
> work?

I am not an expert, but I think no. As I know vtable is placed in object file
that define first non-inline virtual member function of class.

If there is no any non-inline virtual member function vtable is marked "inline"
and is placed in all object files.
Quuxplusone commented 14 years ago
(In reply to comment #23)
> (In reply to comment #22)
> > Shouldn't the error message be something like:
> > "warning: Unimplemented virtual method" and no error, since constructing
should
> > work?
>
> I am not an expert, but I think no. As I know vtable is placed in object file
> that define first non-inline virtual member function of class.
>
> If there is no any non-inline virtual member function vtable is marked
"inline"
> and is placed in all object files.

In your case vtable will be placed in object file that has definition of A::f.
Quuxplusone commented 14 years ago

_Bug 6669 has been marked as a duplicate of this bug._

Quuxplusone commented 14 years ago
(In reply to comment #20)
> Reduced again:
>
> class D {
>         public:
>                 char c;
>                 virtual ~D() {}
> };
> class A : virtual public D {};
> class B : virtual public D {};
> class C : public A, public B {};
>
> int main()
> {
>         C a;
> }

Works now (as of 99391).
Quuxplusone commented 14 years ago
(In reply to comment #22)
> Similarily:
>
> struct A {
>     virtual void f();
> };
>
> int main()
> {
>     A a;
> }
>
> gives:
>
> /tmp/cc-tBz301.o: In function `A::A()':
> a.cc:(.gnu.linkonce.t._ZN1AC2Ev+0x11): undefined reference to `vtable for A'
> collect2: ld returned 1 exit status
> clang: error: linker command failed with exit code 1 (use -v to see
invocation)
>
> Shouldn't the error message be something like:
> "warning: Unimplemented virtual method" and no error, since constructing
should
> work?

Works with clang++ -O2 and -O3, doesn't work with -O1 or without optimization,
also doesn't work with g++ regardless of optimization.
Quuxplusone commented 14 years ago
(In reply to comment #19)
> Further reduced:
>
> class E
> {
>   public:
>     struct _Words {};
>     _Words        _M_word_zero;
>
>     virtual ~E() {}
> };
>
> template<typename _CharT>
> class D : public E
> {};
>
> template<typename _CharT>
> class A : virtual public D<_CharT>
> {};
>
> template<typename _CharT>
> class B : virtual public D<_CharT>
> {
> };
>
> template<typename _CharT>
> class C :        public A <_CharT>,
>             public B<_CharT>
> {
> };
>
> int main()
> {
>     C<char> a;
> }

Works, too.
Quuxplusone commented 14 years ago
(In reply to comment #28)
> (In reply to comment #19)
> > Further reduced:
> >
> > class E
> > {
> >   public:
> >     struct _Words {};
> >     _Words        _M_word_zero;
> >
> >     virtual ~E() {}
> > };
> >
> > template<typename _CharT>
> > class D : public E
> > {};
> >
> > template<typename _CharT>
> > class A : virtual public D<_CharT>
> > {};
> >
> > template<typename _CharT>
> > class B : virtual public D<_CharT>
> > {
> > };
> >
> > template<typename _CharT>
> > class C :        public A <_CharT>,
> >             public B<_CharT>
> > {
> > };
> >
> > int main()
> > {
> >     C<char> a;
> > }
>
> Works, too.

Works regardless of optimization.
Quuxplusone commented 14 years ago
(In reply to comment #18)
> Compiling
>
> #include <ios>
>
> template<typename _CharT>
> class D : public std::ios_base
> {};
>
> template<typename _CharT>
> class A : virtual public D<_CharT>
> {};
>
> template<typename _CharT>
> class B : virtual public D<_CharT>
> {
> };
>
> template<typename _CharT>
> class C :        public A <_CharT>,
>             public B<_CharT>
> {
> };
>
> int main()
> {
>     C<char> a;
> }

Works.
Quuxplusone commented 14 years ago
(In reply to comment #17)
> Reduced testcase:
>
> #include <istream>
>
> int main()
> {
>     std::basic_iostream<char> a;
>     std::basic_iostream<char> b;
> }

Works with -O1, fails with -O2:

*** glibc detected *** ./bla: free(): invalid pointer: 0x4011f7e0 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0x401d5ff1]
/lib/tls/i686/cmov/libc.so.6[0x401d76f2]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x401da7cd]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x400ec6f1]
/usr/lib/libstdc++.so.6(_ZdaPv+0x1d)[0x400ec74d]
/usr/lib/libstdc++.so.6(_ZNSt6locale5_ImplD1Ev+0x7d)[0x4008ba8d]
/usr/lib/libstdc++.so.6(_ZNSt6localeD1Ev+0x4c)[0x4008c09c]
/usr/lib/libstdc++.so.6(_ZNSt8ios_baseD2Ev+0x61)[0x40089041]
./bla[0x8048d77]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x40181b56]
./bla[0x8048c21]
Quuxplusone commented 14 years ago

Attached bugpoint-reduced-simplified.ll (42654 bytes, application/octet-stream): Testcase

Quuxplusone commented 14 years ago
(In reply to comment #32)
> Created an attachment (id=4578) [details]
> Testcase
>
> Testcase from
>
> #include <istream>
> int main()
> {
>         std::basic_iostream<char> a;
>         std::basic_iostream<char> b;
> }
>
> reduced with bugpoint that fails with "opt bugpoint-reduced-simplified.bc
> -simplifycfg -inline -o opted.bc".
> It doesn't fail with only -simplifycfg or -inline.

Gcc doesn't like the C++ file:

/usr/include/c++/4.4/istream: In function ‘int main()’:
/usr/include/c++/4.4/istream:798: error: ‘std::basic_iostream<_CharT,
_Traits>::basic_iostream() [with _CharT = char, _Traits =
std::char_traits<char>]’ is protected
bla.cc:5: error: within this context
/usr/include/c++/4.4/istream:798: error: ‘std::basic_iostream<_CharT,
_Traits>::basic_iostream() [with _CharT = char, _Traits =
std::char_traits<char>]’ is protected
bla.cc:6: error: within this context
Quuxplusone commented 14 years ago
(In reply to comment #17)
> Reduced testcase:
>
> #include <istream>
>
> int main()
> {
>     std::basic_iostream<char> a;
>     std::basic_iostream<char> b;
> }

This doesn't work with gcc, please use the program from comment 16.
Quuxplusone commented 14 years ago

Turns out this wasn't a vtable bug at all.

Committed revision 99829.