Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 27 Dec 2012 16:07:25 +0100
From:      Stefan Farfeleder <stefanf@FreeBSD.org>
To:        current@freebsd.org
Cc:        dim@freebsd.org
Subject:   clang 3.2 RC2 miscompiles libgcc?
Message-ID:  <20121227150724.GA1431@mole.fafoe.narf.at>

next in thread | raw e-mail | index | archive | help
Hi,

I noticed that most of my C++ applications in recent versions of FreeBSD
head suddenly crash without me recompiling them. I tracked it down to
r243830 which imported a new clang version. The new clang seems to
compile libgcc in a wrong or at least incompatible way with what gcc
expects. In fact, the breakage only occurs with libgcc compiled by a
post-r243830 clang and an application compiled with g++ -O2. For me, the
crash happens with boost::program_options, but I'm not sure if that is
necessary for the crash.

$ cat po.cc 
#include <boost/program_options.hpp>

int main(void) {
    namespace po = boost::program_options;
    const char *argv[] = { "a.out", "-x", 0 };
    po::options_description options("Options");
    options.add_options()("bla", "");

    try {
        po::variables_map vm;
        po::store(po::parse_command_line(2, argv, options), vm);
        notify(vm);
        return 0;
    } catch (const std::exception &ex) {
        return 1;
    }
}
$ g++ -O2 -I /usr/local/include -L /usr/local/lib -lboost_program_options po.cc
$ ./a.out 
zsh: segmentation fault (core dumped)  ./a.out
$ ldd ./a.out
./a.out:
        libboost_program_options.so => /usr/local/lib/libboost_program_options.so (0x800821000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x800a7e000)
        libm.so.5 => /lib/libm.so.5 (0x800d7c000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800f9e000)
        libc.so.7 => /lib/libc.so.7 (0x8011ab000)
        libthr.so.3 => /lib/libthr.so.3 (0x801523000)
$ ls /usr/home/stefan/scratch/r243829
libgcc_s.so.1
$ LD_LIBRARY_PATH=/usr/home/stefan/scratch/r243829 ./a.out  
$ valgrind ./a.out
==47491== Memcheck, a memory error detector
==47491== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==47491== Using Valgrind-3.8.0 and LibVEX; rerun with -h for copyright info
==47491== Command: ./a.out
==47491== 
==47491== Invalid read of size 8
==47491==    at 0x405DAA: boost::program_options::basic_parsed_options<char> boost::program_options::parse_command_line<char>(int, char const* const*, boost::program_options::options_description const&, int, boost::function1<std::pair<std::string, std::string>, std::string const&>) (in /usr/home/stefan/scratch/a.out)
==47491==    by 0x401E7D: main (in /usr/home/stefan/scratch/a.out)
==47491==  Address 0x2800ef8 is 24 bytes inside a block of size 27 alloc'd
==47491==    at 0x1009FB6: malloc (in /usr/local/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
==47491==    by 0x213F95A: operator new(unsigned long) (in /usr/lib/libsupc++.so.1)
==47491==    by 0x14F08D2: ??? (in /usr/lib/libstdc++.so.6)
==47491==    by 0x14EDCFD: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&, unsigned long, unsigned long) (in /usr/lib/libstdc++.so.6)
==47491==    by 0x1234B12: boost::program_options::detail::cmdline::parse_short_option(std::vector<std::string, std::allocator<std::string> >&) (in /usr/local/lib/libboost_program_options.so.4)
==47491==    by 0x123843A: boost::detail::function::function_obj_invoker1<boost::_bi::bind_t<std::vector<boost::program_options::basic_option<char>, std::allocator<boost::program_options::basic_option<char> > >, boost::_mfi::mf1<std::vector<boost::program_options::basic_option<char>, std::allocator<boost::program_options::basic_option<char> > >, boost::program_options::detail::cmdline, std::vector<std::string, std::allocator<std::string> >&>, boost::_bi::list2<boost::_bi::value<boost::program_options::detail::cmdline*>, boost::arg<1> > >, std::vector<boost::program_options::basic_option<char>, std::allocator<boost::program_options::basic_option<char> > >, std::vector<std::string, std::allocator<std::string> >&>::invoke(boost::detail::function::function_buffer&, std::vector<std::string, std::allocator<std::string> >&) (in /usr/local/lib/libboost_program_options.so.4)
==47491==    by 0x12367C1: boost::program_options::detail::cmdline::run() (in /usr/local/lib/libboost_program_options.so.4)
==47491==    by 0x4051D5: boost::program_options::basic_command_line_parser<char>::run() (in /usr/home/stefan/scratch/a.out)
==47491==    by 0x405B7A: boost::program_options::basic_parsed_options<char> boost::program_options::parse_command_line<char>(int, char const* const*, boost::program_options::options_description const&, int, boost::function1<std::pair<std::string, std::string>, std::string const&>) (in /usr/home/stefan/scratch/a.out)
==47491==    by 0x401E7D: main (in /usr/home/stefan/scratch/a.out)
==47491== 
==47491== Jump to the invalid address stated on the next line
==47491==    at 0x782D: ???
==47491==    by 0x405DBF: boost::program_options::basic_parsed_options<char> boost::program_options::parse_command_line<char>(int, char const* const*, boost::program_options::options_description const&, int, boost::function1<std::pair<std::string, std::string>, std::string const&>) (in /usr/home/stefan/scratch/a.out)
==47491==    by 0x401E7D: main (in /usr/home/stefan/scratch/a.out)
==47491==  Address 0x782d is not stack'd, malloc'd or (recently) free'd
==47491== 
==47491== 
==47491== Process terminating with default action of signal 11 (SIGSEGV): dumping core
==47491==  Bad permissions for mapped region at address 0x782D
==47491==    at 0x782D: ???
==47491==    by 0x405DBF: boost::program_options::basic_parsed_options<char> boost::program_options::parse_command_line<char>(int, char const* const*, boost::program_options::options_description const&, int, boost::function1<std::pair<std::string, std::string>, std::string const&>) (in /usr/home/stefan/scratch/a.out)
==47491==    by 0x401E7D: main (in /usr/home/stefan/scratch/a.out)
==47491== 
==47491== HEAP SUMMARY:
==47491==     in use at exit: 2,298 bytes in 24 blocks
==47491==   total heap usage: 41 allocs, 17 frees, 2,843 bytes allocated
==47491== 
==47491== LEAK SUMMARY:
==47491==    definitely lost: 184 bytes in 1 blocks
==47491==    indirectly lost: 82 bytes in 2 blocks
==47491==      possibly lost: 88 bytes in 3 blocks
==47491==    still reachable: 1,944 bytes in 18 blocks
==47491==         suppressed: 0 bytes in 0 blocks
==47491== Rerun with --leak-check=full to see details of leaked memory
==47491== 
==47491== For counts of detected and suppressed errors, rerun with: -v
==47491== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)

You might say this is simply a bug in boost that is now uncovered by
chance. I'm not entirely sure it isn't, but I noticed that the
corruption starts at the time the throw statement within the boost code
is executed. I simply wasn't able to reproduce it without boost.
Maybe something within libgcc (some stack unwinding code?) corrupts the
stack. I'm afraid I have no clue about how libgcc and libstdc++
interact wrt to exceptions.

I put copies of a r243829 and r243830 libgcc_s.so.1 to
http://people.freebsd.org/~stefanf/tmp/ .
These were built and installed by buildworld/installworld without any
change of default flags.

Stefan



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20121227150724.GA1431>