This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/77787] New: segfault in mangle.c


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77787

            Bug ID: 77787
           Summary: segfault in mangle.c
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: petschy at gmail dot com
  Target Milestone: ---

Background: while trying to put cold data to a dedicated section I managed to
crash the compiler. The idea was that rarely used strings, eg src file names
and expressions of assertions will be separated from normal data, resulting in
better dcache utilization:

void prn(const char*);
void foo() {
        __attribute__((section(".cold_rodata")))
        static const char x[] = "foo";
        prn(x);
}
inline void bar() {
        __attribute__((section(".cold_rodata")))
        static const char x[] = "bar";
        prn(x);
} 
int main() {
        foo();
        bar();
}

Let's pretend that the x[] arrays were put there by ASSERT() macros.
Unfortunately, this won;t compile:
$ g++ -c 20160928-section_type_conflict.cpp 
20160928-section_type_conflict.cpp:9:20: error: x causes a section type
conflict with x
  static const char x[] = "bar";
                    ^
20160928-section_type_conflict.cpp:4:20: note: ‘x’ was declared here
  static const char x[] = "foo";
                    ^
I know, I know: I shouldn't be using __attribute__ on non-globals.
Unfortunately, there is no hot/cold attribute for data, only for code. For my
specific case, a 'cold' data attribute would partly solve the problem, but
that's probably another discussion.

The explanation can be found here, along with proposed solutions:
http://stackoverflow.com/questions/35091862/inline-static-data-causes-a-section-type-conflict

I thought that rather than messing with __asm__, I go full ret^H^H^Hcrafty:
instead of the static x[], I define a local struct with a static inline fn,
which has the static x[] in the desired section. This way x[] is always in an
inline function, so the conflict goes away. The result: gcc segfaults. 5.4.1,
6.2.1 and 7.0.0 all do it. I built a -g -O0 from 7.0, this is the output:

common/src/dbgmac.h:264:23: internal compiler error: in operator[], at
vec.h:732
    DBG_STRING_DEF(expr_str, #expr); \
                       ^
common/src/platform.h:97:29: note: in definition of macro ‘CONCAT_’
 #define CONCAT_(a_, b_)  a_ ## b_
                          ^~
common/src/platform.h:99:33: note: in expansion of macro ‘CONCAT2’
 #define CONCAT3(a_, b_, c_)  CONCAT2(CONCAT2(a_, b_), c_)
                              ^~~~~~~~~~
common/src/platform.h:98:29: note: in expansion of macro ‘CONCAT_’
 #define CONCAT2(a_, b_)  CONCAT_(a_, b_)
                          ^~~~~~~~~~
common/src/platform.h:99:44: note: in expansion of macro ‘CONCAT2’
 #define CONCAT3(a_, b_, c_)  CONCAT2(CONCAT2(a_, b_), c_)
                                      ^~~~~~~~~~
common/src/dbgmac.h:73:34: note: in expansion of macro ‘CONCAT3’
 #define UNIQ_VAR_NAME(n_)    CONCAT3(n_, _, __LINE__)
                              ^~~~~~~~~~
common/src/dbgmac.h:86:22: note: in expansion of macro ‘UNIQ_VAR_NAME’
    static const char UNIQ_VAR_NAME(var_) [] = val_; \
                      ^~~~~~~~~~~~~~~~~
common/src/dbgmac.h:264:4: note: in expansion of macro ‘DBG_STRING_DEF’
    DBG_STRING_DEF(expr_str, #expr); \
    ^~~~~~~~~~~~~~~~~~
common/src/dbgmac.h:208:35: note: in expansion of macro ‘HARD_ASSERT’
 #define ASSERT(expr, args...) HARD_ASSERT(expr, ## args);
                               ^~~~~~~~~~~~~~~
common/src/json.hpp:1493:2: note: in expansion of macro ‘ASSERT’
  ASSERT(div_ != 0);
  ^~~~~~~~~~
0x7c190a vec<tree_node*, va_gc, vl_embed>::operator[](unsigned int)
        ../../gcc/vec.h:732
0xa2f260 local_class_index
        ../../gcc/cp/mangle.c:1845
0xa2f9ea discriminator_for_local_entity
        ../../gcc/cp/mangle.c:1881
0xa2fd6f write_local_name
        ../../gcc/cp/mangle.c:1972
0xa299c0 write_name
        ../../gcc/cp/mangle.c:917
0xa291f0 write_encoding
        ../../gcc/cp/mangle.c:779
0xa2fb5d write_local_name
        ../../gcc/cp/mangle.c:1941
0xa299c0 write_name
        ../../gcc/cp/mangle.c:917
0xa291f0 write_encoding
        ../../gcc/cp/mangle.c:779
0xa28c89 write_mangled_name
        ../../gcc/cp/mangle.c:744
0xa39b28 mangle_decl_string
        ../../gcc/cp/mangle.c:3709
0xa39b6e get_mangled_id
        ../../gcc/cp/mangle.c:3731
0xa3a032 mangle_decl(tree_node*)
        ../../gcc/cp/mangle.c:3801
0x145f393 decl_assembler_name(tree_node*)
        ../../gcc/tree.c:669
0xbd4c72 symbol_table::insert_to_assembler_name_hash(symtab_node*, bool)
        ../../gcc/symtab.c:171
0xbd4fef symbol_table::symtab_initialize_asm_name_hash()
        ../../gcc/symtab.c:263
0xbd71dc symtab_node::get_for_asmname(tree_node const*)
        ../../gcc/symtab.c:930
0xbf366d handle_alias_pairs
        ../../gcc/cgraphunit.c:1258
0xbf75e2 symbol_table::finalize_compilation_unit()
        ../../gcc/cgraphunit.c:2541
Please submit a full bug report,

Nothing fancy on the command line, just -I's -D's, does it with -O0 and -O3,
too (though since it's probably a mangle bug, the optimization level should not
matter).

Unfortunately, this is a closed source project, so I can't post the
[preprocessed] code. I tried to reduce it, but as luck would have it, then
everything goes just fine. Here is the reduced test:

#include <stdio.h>

#define CONCAT_(a_, b_)                 a_ ## b_
#define CONCAT2(a_, b_)                 CONCAT_(a_, b_)
#define CONCAT3(a_, b_, c_)             CONCAT2(CONCAT2(a_, b_), c_)
#define CONCAT4(a_, b_, c_, d_)         CONCAT2(CONCAT3(a_, b_, c_), d_)

#define LIKELY(expr_)                   __builtin_expect(!!(expr_), 1)
#define UNLIKELY(expr_)                 __builtin_expect(!!(expr_), 0)

#define UNIQ_VAR_NAME(n_)               CONCAT3(n_, _, __LINE__)

#define DBG_STRING_DEF(var_, val_) \
        struct CONCAT4(DbgStringDefHelper_, var_, _, __LINE__) { \
                static inline const char* Get() { \
                        __attribute__((section(".rodata.cold.debug"))) \
                        static const char UNIQ_VAR_NAME(var_) [] = val_; \
                        return UNIQ_VAR_NAME(var_); \
                } \
        }
#define DBG_STRING_GET(var_)            CONCAT4(DbgStringDefHelper_, var_, _,
__LINE__)::Get()

#define ASSERT(expr, args...) \
        if (LIKELY(expr)) { } else \
        { \
                DBG_STRING_DEF(file_str, __FILE__); \
                DBG_STRING_DEF(expr_str, #expr); \
                dbg_assert(DBG_STRING_GET(file_str), __LINE__,
DBG_STRING_GET(expr_str), ## args); \
        }

void dbg_assert(const char* file_, int line_, const char* expr_, ...)
{
        fprintf(stderr, "%s:%d: ASSERTION FAILED: '%s' is FALSE\n", file_,
line_, expr_);
}

namespace baz {

//inline
void foo(int x)
{
        ASSERT(x == 42);
}

template<typename T>
//inline
void bar(T x)
{
        ASSERT(x == 42);
}

} // ns baz

int main()
{
        using namespace baz;
        foo(23);
        bar(11);
}

I tried to make the functions inline, and/or putting them in the global
namespace, but no luck.

The error message says that the bug was triggered by the assertion in the json
header at line 1493. That's in a free standing function template, the last one
in the header and in the whole preprocessed compilation unit. If I delete the
fn from the header, the error remains, but then it is reported on the previous
fn. If I delete many functions, the error remains, but moves to a different
header. There are 28 assertions total, so I though maybe that's too much, but
putting 30 assertions in bar() didn't trigger the error. I ran out of immediate
ideas.

I have the core dump, the error is 100% reproducible, just not in the reduced
test. If you have ideas how to extract more info, please let me know.
Meanwhile, I will try to enhance the test to trigger.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]