If you link with -rdynamic you can show a backtrace with something like the attached code.
On Wed, Aug 29, 2012 at 9:22 AM, Ian Lance Taylor <i...@google.com> wrote: > I've spent the last couple of days working on a stack backtrace library. > > It uses the GCC unwind interface to collect a stack trace, and parses > DWARF debug info to get file/line/function information. (Of course it's > silly to write yet another DWARF reader, but I didn't find an existing > reader that seemed wholly suitable.) The code currently only works for > ELF/DWARF, but it's designed to support other object file and debug > formats should anybody care to write them. Since its use in GCC would > be purely for GCC developers, it's not essential that it be fully > portable. > > > I picked a random PR that causes an ICE. Here is the final output of > g++ -c foo.cc: > > foo.cc:6:6: internal compiler error: in cp_lexer_new_from_tokens, at > cp/parser.c:638 > 0xed6e77 diagnostic_report_diagnostic(diagnostic_context*, diagnostic_info*) > ../../trunk/gcc/diagnostic.c:700 > 0xed7c2f internal_error(char const*, ...) > ../../trunk/gcc/diagnostic.c:1003 > 0xed6703 fancy_abort(char const*, int, char const*) > ../../trunk/gcc/diagnostic.c:1057 > 0x5bc3ee cp_lexer_new_from_tokens > ../../trunk/gcc/cp/parser.c:638 > 0x5bc3ee cp_parser_push_lexer_for_tokens > ../../trunk/gcc/cp/parser.c:3293 > 0x5c5510 cp_parser_late_parsing_for_member > ../../trunk/gcc/cp/parser.c:21741 > 0x5c5510 cp_parser_class_specifier_1 > ../../trunk/gcc/cp/parser.c:18210 > 0x5c5510 cp_parser_class_specifier > ../../trunk/gcc/cp/parser.c:18234 > 0x5c5510 cp_parser_type_specifier > ../../trunk/gcc/cp/parser.c:13393 > 0x5dd56d cp_parser_decl_specifier_seq > ../../trunk/gcc/cp/parser.c:10734 > 0x5e00d7 cp_parser_single_declaration > ../../trunk/gcc/cp/parser.c:21344 > 0x5e1211 cp_parser_template_declaration_after_export > ../../trunk/gcc/cp/parser.c:21231 > 0x5ea9f9 cp_parser_declaration > ../../trunk/gcc/cp/parser.c:10186 > 0x5e9507 cp_parser_declaration_seq_opt > ../../trunk/gcc/cp/parser.c:10108 > 0x5eae92 cp_parser_translation_unit > ../../trunk/gcc/cp/parser.c:3760 > 0x5eae92 c_parse_file() > ../../trunk/gcc/cp/parser.c:27585 > 0x6ed0c4 c_common_parse_file() > ../../trunk/gcc/c-family/c-opts.c:1137 > 0xa2017b compile_file > ../../trunk/gcc/toplev.c:546 > 0xa21d89 do_compile > ../../trunk/gcc/toplev.c:1863 > 0xa21d89 toplev_main(int, char**) > ../../trunk/gcc/toplev.c:1939 > 0x7fb0a50d8c4c ??? > ???:0 > 0x4c6db8 ??? > ???:0 > Please submit a full bug report, > with preprocessed source if appropriate. > See <http://gcc.gnu.org/bugs.html> for instructions. > > > So, big deal. You can get a stack backtrace from gdb anyhow. > > For a more interesting use I hacked ggc-common.c to collect detailed > statistics when used with -fmem-report. This gives us data similar to, > and better than, that you get when you configure GCC with > --enable-gather-detailed-mem-stats. However, with this approach you do > not need to recompile GCC. Running this modified GCC with -fmem-report > -O2 -g combine.ii took 36 seconds. The full report is too large to > attach here, but here are the last few entries of the ggc-common.c. > Note that I spent exactly 0 seconds making the report pretty. > > 0xbf1151 ../../trunk/gcc/tree.c:7607 build_function_type(tree_node*, > tree_node*) > 0x50f1c0 ../../trunk/gcc/cp/decl.c:9346 grokdeclarator(cp_declarator const*, > cp_decl_specifier_seq const*, decl_context, int, tree_node**) > 0x514a75 ../../trunk/gcc/cp/decl.c:4366 start_decl(cp_declarator const*, > cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) > 0x5dbeca ../../trunk/gcc/cp/parser.c:15720 cp_parser_init_declarator > 0x5de4ba ../../trunk/gcc/cp/parser.c:10445 cp_parser_simple_declaration > 0x5e6337 ../../trunk/gcc/cp/parser.c:10326 cp_parser_block_declaration > 0x5ea8fb ../../trunk/gcc/cp/parser.c:10222 cp_parser_declaration > 0x5e9507 ../../trunk/gcc/cp/parser.c:10108 cp_parser_declaration_seq_opt > 0x5eae92 ../../trunk/gcc/cp/parser.c:3760 cp_parser_translation_unit > 0x5eae92 ../../trunk/gcc/cp/parser.c:27585 c_parse_file() > 0x6ed0c4 ../../trunk/gcc/c-family/c-opts.c:1137 c_common_parse_file() > 0xa2017b ../../trunk/gcc/toplev.c:546 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 611352: 1.0% 0: 0.0% 181776: 0.6% 0: 0.0% 4721 > 0xbf342f ../../trunk/gcc/tree.c:1224 build_int_cst_wide(tree_node*, unsigned > long, long) > 0xbf37a5 ../../trunk/gcc/tree.c:1065 double_int_to_tree(tree_node*, > double_int) > 0xbf37ea ../../trunk/gcc/tree.c:1042 build_int_cst(tree_node*, long) > 0xa19fee ../../trunk/gcc/stor-layout.c:2545 > set_min_and_max_values_for_integral_type(tree_node*, int, bool) > 0x502788 ../../trunk/gcc/cp/decl.c:12345 finish_enum_value_list(tree_node*) > 0x5d53d4 ../../trunk/gcc/cp/parser.c:14609 cp_parser_enum_specifier > 0x5c4c1d ../../trunk/gcc/cp/parser.c:13365 cp_parser_type_specifier > 0x5dd56d ../../trunk/gcc/cp/parser.c:10734 cp_parser_decl_specifier_seq > 0x5de309 ../../trunk/gcc/cp/parser.c:10377 cp_parser_simple_declaration > 0x5e6337 ../../trunk/gcc/cp/parser.c:10326 cp_parser_block_declaration > 0x5ea8fb ../../trunk/gcc/cp/parser.c:10222 cp_parser_declaration > 0x5e9507 ../../trunk/gcc/cp/parser.c:10108 cp_parser_declaration_seq_opt > 0x5eae92 ../../trunk/gcc/cp/parser.c:3760 cp_parser_translation_unit > 0x5eae92 ../../trunk/gcc/cp/parser.c:27585 c_parse_file() > 0x6ed0c4 ../../trunk/gcc/c-family/c-opts.c:1137 c_common_parse_file() > 0xa2017b ../../trunk/gcc/toplev.c:546 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 0: 0.0% 0: 0.0% 837344: 2.8% 276192:16.2% 137 > 0xc147e7 ../../trunk/gcc/var-tracking.c:8568 emit_note_insn_var_location > 0xf18f08 ../../trunk/libiberty/hashtab.c:784 htab_traverse > 0xc22ea7 ../../trunk/gcc/var-tracking.c:8756 emit_notes_for_changes > 0xc23054 ../../trunk/gcc/var-tracking.c:8870 emit_notes_for_differences > 0xc23054 ../../trunk/gcc/var-tracking.c:9245 vt_emit_notes > 0xc23b49 ../../trunk/gcc/var-tracking.c:10048 variable_tracking_main_1 > 0xc23b49 ../../trunk/gcc/var-tracking.c:10062 variable_tracking_main() > 0x97de5e ../../trunk/gcc/passes.c:2157 execute_one_pass(opt_pass*) > 0x97e214 ../../trunk/gcc/passes.c:2212 execute_pass_list(opt_pass*) > 0x97e226 ../../trunk/gcc/passes.c:2213 execute_pass_list(opt_pass*) > 0x97e226 ../../trunk/gcc/passes.c:2213 execute_pass_list(opt_pass*) > 0x7782d7 ../../trunk/gcc/cgraphunit.c:1609 expand_function > 0x77a179 ../../trunk/gcc/cgraphunit.c:1714 expand_all_functions > 0x77a179 ../../trunk/gcc/cgraphunit.c:2012 compile() > 0x77a774 ../../trunk/gcc/cgraphunit.c:2089 finalize_compilation_unit() > 0x5aa0ba ../../trunk/gcc/cp/decl2.c:4024 cp_write_global_declarations() > 0xa201c4 ../../trunk/gcc/toplev.c:560 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 872704: 1.5% 0: 0.0% 0: 0.0% 0: 0.0% 13636 > 0xbf03e8 ../../trunk/gcc/tree.c:4093 build_decl_stat(unsigned int, tree_code, > tree_node*, tree_node*) > 0x5bb085 ../../trunk/gcc/cp/lex.c:532 build_lang_decl_loc(unsigned int, > tree_code, tree_node*, tree_node*) > 0x516729 ../../trunk/gcc/cp/decl.c:7175 grokfndecl > 0x5129fd ../../trunk/gcc/cp/decl.c:10394 grokdeclarator(cp_declarator const*, > cp_decl_specifier_seq const*, decl_context, int, tree_node**) > 0x514a75 ../../trunk/gcc/cp/decl.c:4366 start_decl(cp_declarator const*, > cp_decl_specifier_seq*, int, tree_node*, tree_node*, tree_node**) > 0x5dbeca ../../trunk/gcc/cp/parser.c:15720 cp_parser_init_declarator > 0x5de4ba ../../trunk/gcc/cp/parser.c:10445 cp_parser_simple_declaration > 0x5e6337 ../../trunk/gcc/cp/parser.c:10326 cp_parser_block_declaration > 0x5ea8fb ../../trunk/gcc/cp/parser.c:10222 cp_parser_declaration > 0x5e9507 ../../trunk/gcc/cp/parser.c:10108 cp_parser_declaration_seq_opt > 0x5eae92 ../../trunk/gcc/cp/parser.c:3760 cp_parser_translation_unit > 0x5eae92 ../../trunk/gcc/cp/parser.c:27585 c_parse_file() > 0x6ed0c4 ../../trunk/gcc/c-family/c-opts.c:1137 c_common_parse_file() > 0xa2017b ../../trunk/gcc/toplev.c:546 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 0: 0.0% 864: 0.0% 1348128: 4.5% 149888: 8.8% 4684 > 0xb86a21 ../../trunk/gcc/tree-ssanames.c:140 make_ssa_name_fn(function*, > tree_node*, gimple_statement_d*) > 0xa7a3c1 ../../trunk/gcc/tree-flow-inline.h:1144 make_ssa_name > 0xa7a3c1 ../../trunk/gcc/tree-into-ssa.c:1396 rewrite_stmt > 0xa7a3c1 ../../trunk/gcc/tree-into-ssa.c:1471 rewrite_enter_block > 0xe275fa ../../trunk/gcc/domwalk.c:188 walk_dominator_tree(dom_walk_data*, > basic_block_def*) > 0xa7bc70 ../../trunk/gcc/tree-into-ssa.c:2265 rewrite_blocks > 0xa7bf97 ../../trunk/gcc/tree-into-ssa.c:2432 rewrite_into_ssa > 0x97de5e ../../trunk/gcc/passes.c:2157 execute_one_pass(opt_pass*) > 0x97e214 ../../trunk/gcc/passes.c:2212 execute_pass_list(opt_pass*) > 0x97d37c ../../trunk/gcc/passes.c:1702 do_per_function_toporder(void > (*)(void*), void*) > 0x97e6ab ../../trunk/gcc/passes.c:2526 execute_ipa_pass_list(opt_pass*) > 0x779fe1 ../../trunk/gcc/cgraphunit.c:1838 ipa_passes > 0x779fe1 ../../trunk/gcc/cgraphunit.c:1961 compile() > 0x77a774 ../../trunk/gcc/cgraphunit.c:2089 finalize_compilation_unit() > 0x5aa0ba ../../trunk/gcc/cp/decl2.c:4024 cp_write_global_declarations() > 0xa201c4 ../../trunk/gcc/toplev.c:560 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 1005760: 1.7% 0: 0.0% 359680: 1.2% 0: 0.0% 17068 > 0xa1ca7d ../../trunk/gcc/stringpool.c:75 alloc_node > 0xef2dc7 ../../trunk/libcpp/symtab.c:158 ht_lookup_with_hash(ht*, unsigned > char const*, unsigned long, unsigned int, ht_lookup_option) > 0xee88de ../../trunk/libcpp/lex.c:1232 lex_identifier > 0xeeadcf ../../trunk/libcpp/lex.c:2205 _cpp_lex_direct > 0xeeb96b ../../trunk/libcpp/lex.c:1974 _cpp_lex_token > 0xeefce7 ../../trunk/libcpp/macro.c:2357 cpp_get_token_1 > 0x6e6622 ../../trunk/gcc/c-family/c-lex.c:299 c_lex_with_flags(tree_node**, > unsigned int*, unsigned char*, int) > 0x5bf66f ../../trunk/gcc/cp/parser.c:719 cp_lexer_get_preprocessor_token > 0x5ead40 ../../trunk/gcc/cp/parser.c:598 cp_lexer_new_main > 0x5ead40 ../../trunk/gcc/cp/parser.c:3216 cp_parser_new > 0x5ead40 ../../trunk/gcc/cp/parser.c:27582 c_parse_file() > 0x6ed0c4 ../../trunk/gcc/c-family/c-opts.c:1137 c_common_parse_file() > 0xa2017b ../../trunk/gcc/toplev.c:546 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 16016: 0.0% 0: 0.0% 1564728: 5.2% 0: 0.0% 17963 > 0xbf03e8 ../../trunk/gcc/tree.c:4093 build_decl_stat(unsigned int, tree_code, > tree_node*, tree_node*) > 0x59de96 ../../trunk/gcc/cp/decl2.c:181 cp_build_parm_decl(tree_node*, > tree_node*) > 0x5133de ../../trunk/gcc/cp/decl.c:10054 grokdeclarator(cp_declarator const*, > cp_decl_specifier_seq const*, decl_context, int, tree_node**) > 0x5defbc ../../trunk/gcc/cp/parser.c:17116 > cp_parser_parameter_declaration_list > 0x5df444 ../../trunk/gcc/cp/parser.c:17030 > cp_parser_parameter_declaration_clause > 0x5d6aee ../../trunk/gcc/cp/parser.c:16090 cp_parser_direct_declarator > 0x5d6aee ../../trunk/gcc/cp/parser.c:15961 cp_parser_declarator > 0x5dbb67 ../../trunk/gcc/cp/parser.c:15537 cp_parser_init_declarator > 0x5de4ba ../../trunk/gcc/cp/parser.c:10445 cp_parser_simple_declaration > 0x5e6337 ../../trunk/gcc/cp/parser.c:10326 cp_parser_block_declaration > 0x5ea8fb ../../trunk/gcc/cp/parser.c:10222 cp_parser_declaration > 0x5e9507 ../../trunk/gcc/cp/parser.c:10108 cp_parser_declaration_seq_opt > 0x5eae92 ../../trunk/gcc/cp/parser.c:3760 cp_parser_translation_unit > 0x5eae92 ../../trunk/gcc/cp/parser.c:27585 c_parse_file() > 0x6ed0c4 ../../trunk/gcc/c-family/c-opts.c:1137 c_common_parse_file() > 0xa2017b ../../trunk/gcc/toplev.c:546 compile_file > 0xa21d89 ../../trunk/gcc/toplev.c:1863 do_compile > 0xa21d89 ../../trunk/gcc/toplev.c:1939 toplev_main(int, char**) > 0x7f4044f36c4c ???:0 ??? > 0x4c6db8 ???:0 ??? > 32640: 0.1% 0: 0.0% 1555328: 5.2% 0: 0.0% 12406 > Total 59553548 38936868 > 29879567 1701879 1921781 > Garbage Freed Leak Overhead > Times > > > > As you can see, this gives us the opportunity for some fairly detailed > analysis of where we are allocating memory, without requiring the > compiler to be recompiled, and without taking an inordinate amount of > time. > > > I expect to use this code not just for GCC proper, but also for libgo > (currently libgo uses Go code to parse DWARF, but that is not very > satisfactory as that code is only available if it has been imported into > the program). So I put it under a BSD license, although that is open > for discussion. Also in case it finds more uses elsewhere I wrote it in > reasonably portable C rather than C++. > > > I've attached two patches. The first is the patch for the libbacktrace > library, plus the changes to the top level configure.ac and > Makefile.def. The second is the changes to GCC proper that I used to > generate the above dumps. The second patch is just quick and dirty work > to see if the library could work well. > > > Does this seem like something we could usefully add to GCC? Does > anybody see any big problems with it? > > The library is not quite ready to commit, but it's quite close. It just > needs a bit more testing in uncommon build environments, i.e., anything > other than x86_64 GNU/Linux, to make sure that it at least builds and > does not crash even when it can't get a backtrace. > > Ian > >
bt.cc
Description: Binary data