[PATCH][debug] Add debug and earlydebug dumps
Richard Biener
rguenther@suse.de
Mon Aug 20 12:25:00 GMT 2018
On Mon, 13 Aug 2018, Tom de Vries wrote:
> Hi,
>
> With the introduction of early debug, we've added a phase in the compiler which
> produces information which is not visible, unless we run the compiler in the
> debugger and call debug_dwarf from dwarf2out_early_finish or some such.
>
> This patch adds dumping of "early" and "final" debug info, into .earlydebug
> and .debug dump files, such that we can follow f.i. the upper bound of a vla
> type from early debug:
> ...
> DW_AT_upper_bound: location descriptor:
> (0x7f0d645b7550) DW_OP_GNU_variable_value , 0
> ...
> to final debug:
> ...
> DW_AT_upper_bound: location descriptor:
> (0x7f0d645b7550) DW_OP_fbreg 18446744073709551592, 0
> (0x7f0d645b7a00) DW_OP_deref 8, 0
> ...
> to -dA annotated assembly file:
> ...
> .uleb128 0x3 # DW_AT_upper_bound
> .byte 0x91 # DW_OP_fbreg
> .sleb128 -24
> .byte 0x6 # DW_OP_deref
> ...
>
> The .debug file shows the same information as the annotated assembly, but in
> the same format as the "early" debug info.
>
> Bootstrapped and reg-tested on x86_64.
>
> OK for trunk?
OK. Can you document the options to trigger those dumps?
I suppose -fdump-tree-earlydebug and -fdump-tree-debug?
Thanks,
Richard.
> Thanks,
> - Tom
>
> [debug] Add debug and earlydebug dumps
>
> 2018-08-13 Tom de Vries <tdevries@suse.de>
>
> * cgraph.h (debuginfo_early_init, debuginfo_init, debuginfo_fini)
> (debuginfo_start, debuginfo_stop, debuginfo_early_start)
> (debuginfo_early_stop): Declare.
> * cgraphunit.c (debuginfo_early_init, debuginfo_init, debuginfo_fini)
> (debuginfo_start, debuginfo_stop, debuginfo_early_start)
> (debuginfo_early_stop): New function.
> (symbol_table::finalize_compilation_unit): Call debuginfo_early_start
> and debuginfo_early_stop.
> * dwarf2out.c (print_dw_val, print_loc_descr, print_die): Handle
> flag_dump_noaddr and flag_dump_unnumbered.
> (dwarf2out_finish, dwarf2out_early_finish): Dump dwarf.
> * toplev.c (compile_file): Call debuginfo_start and debuginfo_stop.
> (general_init): Call debuginfo_early_init.
> (finalize): Call debuginfo_fini.
> (do_compile): Call debuginfo_init.
>
> * lto.c (lto_main): Call debuginfo_early_start and
> debuginfo_early_stop.
>
> * gcc.c-torture/unsorted/dump-noaddr.x: Skip earlydebug and debug dumps.
>
> ---
> gcc/cgraph.h | 8 +++
> gcc/cgraphunit.c | 66 ++++++++++++++++++++++
> gcc/dwarf2out.c | 46 ++++++++++++---
> gcc/lto/lto.c | 2 +
> gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x | 7 +++
> gcc/toplev.c | 5 ++
> 6 files changed, 126 insertions(+), 8 deletions(-)
>
> diff --git a/gcc/cgraph.h b/gcc/cgraph.h
> index a8b1b4cb3c3..2b00f0165fa 100644
> --- a/gcc/cgraph.h
> +++ b/gcc/cgraph.h
> @@ -25,6 +25,14 @@ along with GCC; see the file COPYING3. If not see
> #include "ipa-ref.h"
> #include "plugin-api.h"
>
> +extern void debuginfo_early_init (void);
> +extern void debuginfo_init (void);
> +extern void debuginfo_fini (void);
> +extern void debuginfo_start (void);
> +extern void debuginfo_stop (void);
> +extern void debuginfo_early_start (void);
> +extern void debuginfo_early_stop (void);
> +
> class ipa_opt_pass_d;
> typedef ipa_opt_pass_d *ipa_opt_pass;
>
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 462e247328e..6649942c4fb 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -2636,6 +2636,70 @@ symbol_table::compile (void)
> }
> }
>
> +static int debuginfo_early_dump_nr;
> +static FILE *debuginfo_early_dump_file;
> +static dump_flags_t debuginfo_early_dump_flags;
> +
> +static int debuginfo_dump_nr;
> +static FILE *debuginfo_dump_file;
> +static dump_flags_t debuginfo_dump_flags;
> +
> +void
> +debuginfo_early_init (void)
> +{
> + gcc::dump_manager *dumps = g->get_dumps ();
> + debuginfo_early_dump_nr = dumps->dump_register (".earlydebug", "earlydebug",
> + "earlydebug", DK_tree,
> + OPTGROUP_NONE,
> + false);
> + debuginfo_dump_nr = dumps->dump_register (".debug", "debug",
> + "debug", DK_tree,
> + OPTGROUP_NONE,
> + false);
> +}
> +
> +void
> +debuginfo_init (void)
> +{
> + gcc::dump_manager *dumps = g->get_dumps ();
> + debuginfo_dump_file = dump_begin (debuginfo_dump_nr, NULL);
> + debuginfo_dump_flags = dumps->get_dump_file_info (debuginfo_dump_nr)->pflags;
> + debuginfo_early_dump_file = dump_begin (debuginfo_early_dump_nr, NULL);
> + debuginfo_early_dump_flags = dumps->get_dump_file_info (debuginfo_early_dump_nr)->pflags;
> +}
> +
> +void
> +debuginfo_fini (void)
> +{
> + if (debuginfo_dump_file)
> + dump_end (debuginfo_dump_nr, debuginfo_dump_file);
> + if (debuginfo_early_dump_file)
> + dump_end (debuginfo_early_dump_nr, debuginfo_early_dump_file);
> +}
> +
> +void
> +debuginfo_start (void)
> +{
> + set_dump_file (debuginfo_dump_file);
> +}
> +
> +void
> +debuginfo_stop (void)
> +{
> + set_dump_file (NULL);
> +}
> +
> +void
> +debuginfo_early_start (void)
> +{
> + set_dump_file (debuginfo_early_dump_file);
> +}
> +
> +void
> +debuginfo_early_stop (void)
> +{
> + set_dump_file (NULL);
> +}
>
> /* Analyze the whole compilation unit once it is parsed completely. */
>
> @@ -2691,7 +2755,9 @@ symbol_table::finalize_compilation_unit (void)
>
> /* Clean up anything that needs cleaning up after initial debug
> generation. */
> + debuginfo_early_start ();
> (*debug_hooks->early_finish) (main_input_filename);
> + debuginfo_early_stop ();
> }
>
> /* Finally drive the pass manager. */
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 9ed473088e7..4b63cbd8a1e 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -6455,7 +6455,12 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
> print_indent -= 4;
> }
> else
> - fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
> + {
> + if (flag_dump_noaddr || flag_dump_unnumbered)
> + fprintf (outfile, " #\n");
> + else
> + fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
> + }
> break;
> case dw_val_class_loc_list:
> fprintf (outfile, "location list -> label:%s",
> @@ -6524,7 +6529,10 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
> }
> else
> fprintf (outfile, "die -> %ld", die->die_offset);
> - fprintf (outfile, " (%p)", (void *) die);
> + if (flag_dump_noaddr || flag_dump_unnumbered)
> + fprintf (outfile, " #");
> + else
> + fprintf (outfile, " (%p)", (void *) die);
> }
> else
> fprintf (outfile, "die -> <null>");
> @@ -6614,8 +6622,11 @@ print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
> for (l = loc; l != NULL; l = l->dw_loc_next)
> {
> print_spaces (outfile);
> - fprintf (outfile, "(%p) %s",
> - (void *) l,
> + if (flag_dump_noaddr || flag_dump_unnumbered)
> + fprintf (outfile, "#");
> + else
> + fprintf (outfile, "(%p)", (void *) l);
> + fprintf (outfile, " %s",
> dwarf_stack_op_name (l->dw_loc_opc));
> if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
> {
> @@ -6642,9 +6653,12 @@ print_die (dw_die_ref die, FILE *outfile)
> unsigned ix;
>
> print_spaces (outfile);
> - fprintf (outfile, "DIE %4ld: %s (%p)\n",
> - die->die_offset, dwarf_tag_name (die->die_tag),
> - (void*) die);
> + fprintf (outfile, "DIE %4ld: %s ",
> + die->die_offset, dwarf_tag_name (die->die_tag));
> + if (flag_dump_noaddr || flag_dump_unnumbered)
> + fprintf (outfile, "#\n");
> + else
> + fprintf (outfile, "(%p)\n", (void*) die);
> print_spaces (outfile);
> fprintf (outfile, " abbrev id: %lu", die->die_abbrev);
> fprintf (outfile, " offset: %ld", die->die_offset);
> @@ -31088,7 +31102,7 @@ reset_dies (dw_die_ref die)
> and generate the DWARF-2 debugging info. */
>
> static void
> -dwarf2out_finish (const char *)
> +dwarf2out_finish (const char *filename)
> {
> comdat_type_node *ctnode;
> dw_die_ref main_comp_unit_die;
> @@ -31169,6 +31183,12 @@ dwarf2out_finish (const char *)
> resolve_addr (comp_unit_die ());
> move_marked_base_types ();
>
> + if (dump_file)
> + {
> + fprintf (dump_file, "DWARF for %s\n", filename);
> + print_die (comp_unit_die (), dump_file);
> + }
> +
> /* Initialize sections and labels used for actual assembler output. */
> unsigned generation = init_sections_and_labels (false);
>
> @@ -31864,6 +31884,11 @@ dwarf2out_early_finish (const char *filename)
> if (in_lto_p)
> {
> early_dwarf_finished = true;
> + if (dump_file)
> + {
> + fprintf (dump_file, "LTO EARLY DWARF for %s\n", filename);
> + print_die (comp_unit_die (), dump_file);
> + }
> return;
> }
>
> @@ -31941,6 +31966,11 @@ dwarf2out_early_finish (const char *filename)
>
> /* The early debug phase is now finished. */
> early_dwarf_finished = true;
> + if (dump_file)
> + {
> + fprintf (dump_file, "EARLY DWARF for %s\n", filename);
> + print_die (comp_unit_die (), dump_file);
> + }
>
> /* Do not generate DWARF assembler now when not producing LTO bytecode. */
> if ((!flag_generate_lto && !flag_generate_offload)
> diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> index 8db280ecefc..10618896022 100644
> --- a/gcc/lto/lto.c
> +++ b/gcc/lto/lto.c
> @@ -3419,7 +3419,9 @@ lto_main (void)
> lto_promote_statics_nonwpa ();
>
> /* Annotate the CU DIE and mark the early debug phase as finished. */
> + debuginfo_early_start ();
> debug_hooks->early_finish ("<artificial>");
> + debuginfo_early_stop ();
>
> /* Let the middle end know that we have read and merged all of
> the input files. */
> diff --git a/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x b/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
> index e86f36a1861..d2be9c001e0 100644
> --- a/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
> +++ b/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
> @@ -19,6 +19,13 @@ proc dump_compare { src options } {
> set dump2 "$tmpdir/dump2/[file tail $dump1]"
> set dumptail "gcc.c-torture/unsorted/[file tail $dump1]"
> regsub {\.\d+((t|r|i)\.[^.]+)$} $dumptail {.*\1} dumptail
> + if { "$dumptail" == "gcc.c-torture/unsorted/dump-noaddr.c.*t.earlydebug"
> + || "$dumptail" == "gcc.c-torture/unsorted/dump-noaddr.c.*t.debug" } {
> + # The DW_AT_producer line contains the command line options so, this will
> + # fail on dump1 having '--param ggc-min-heapsize=1', and dump2 not.
> + untested "$dumptail, $option comparison"
> + continue
> + }
> set tmp [ diff "$dump1" "$dump2" ]
> if { $tmp == 0 } {
> untested "$dumptail, $option comparison"
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index aa943a8655e..d28bff01552 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -529,7 +529,9 @@ compile_file (void)
> dwarf2out_frame_finish ();
> #endif
>
> + debuginfo_start ();
> (*debug_hooks->finish) (main_input_filename);
> + debuginfo_stop ();
> timevar_pop (TV_SYMOUT);
>
> /* Output some stuff at end of file if nec. */
> @@ -1185,6 +1187,7 @@ general_init (const char *argv0, bool init_signals)
> symtab = new (ggc_cleared_alloc <symbol_table> ()) symbol_table ();
>
> statistics_early_init ();
> + debuginfo_early_init ();
> finish_params ();
> }
>
> @@ -2079,6 +2082,7 @@ finalize (bool no_backend)
> if (!no_backend)
> {
> statistics_fini ();
> + debuginfo_fini ();
>
> g->get_passes ()->finish_optimization_passes ();
>
> @@ -2156,6 +2160,7 @@ do_compile ()
> init_final (main_input_filename);
> coverage_init (aux_base_name);
> statistics_init ();
> + debuginfo_init ();
> invoke_plugin_callbacks (PLUGIN_START_UNIT, NULL);
>
> timevar_stop (TV_PHASE_SETUP);
>
>
--
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)
More information about the Gcc-patches
mailing list