[debug] Add debug and earlydebug dumps

Message ID 20180813182537.GA1874@delia
State New
Headers show
Series
  • [debug] Add debug and earlydebug dumps
Related show

Commit Message

Tom de Vries Aug. 13, 2018, 6:25 p.m.
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?

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(-)

Comments

Richard Biener Aug. 20, 2018, 12:24 p.m. | #1
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)
Tom de Vries Aug. 21, 2018, 7:54 a.m. | #2
On 08/20/2018 02:24 PM, Richard Biener wrote:
> 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?


Done.

> I suppose -fdump-tree-earlydebug and -fdump-tree-debug?


No, they're -fdump-earlydebug and -fdump-debug, but they're members of
the tree family, so they're enabled with fdump-tree-all, which is the
same behaviour as we have for -fdump-statistics.

Apart from adding docs, I've:
- improved the workaround in unsorted/dump-noaddr.x, after learning
  about -grecord-gcc-switches
- fixed 2 formatting issues (line longer than 80, leading whitespace
  inconsistent with adjacent lines)
- added comments to new functions and global variables
- split off "[debug] Respect fdump-noaddr and fdump-unnumbered in
  print_die" as separate patch, and committed (not reposting).

Committed as attached.

Thanks,
- Tom
[debug] Add debug and earlydebug dumps

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, enabled by -fdump-earlydebug and -fdumpdebug, 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.

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 (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.
	* doc/invoke.texi (@gccoptlist): Add -fdump-debug and
	-fdump-early-debug.
	(@item -fdump-debug, @item -fdump-earlydebug): Add.

	* lto.c (lto_main):  Call debuginfo_early_start and
	debuginfo_early_stop.

	* gcc.c-torture/unsorted/dump-noaddr.x: Use -gno-record-gcc-switches
	to avoid mismatch in .debug and .earlydebug dump files.

---
 gcc/cgraph.h                                       |  8 ++
 gcc/cgraphunit.c                                   | 85 ++++++++++++++++++++++
 gcc/doc/invoke.texi                                | 11 +++
 gcc/dwarf2out.c                                    | 18 ++++-
 gcc/lto/lto.c                                      |  2 +
 gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x |  4 +-
 gcc/toplev.c                                       |  5 ++
 7 files changed, 130 insertions(+), 3 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..e43c96a4043 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -2636,6 +2636,89 @@ symbol_table::compile (void)
     }
 }
 
+/* Earlydebug dump file, flags, and number.  */
+
+static int debuginfo_early_dump_nr;
+static FILE *debuginfo_early_dump_file;
+static dump_flags_t debuginfo_early_dump_flags;
+
+/* Debug dump file, flags, and number.  */
+
+static int debuginfo_dump_nr;
+static FILE *debuginfo_dump_file;
+static dump_flags_t debuginfo_dump_flags;
+
+/* Register the debug and earlydebug dump files.  */
+
+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);
+}
+
+/* Initialize the debug and earlydebug dump files.  */
+
+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;
+}
+
+/* Finalize the debug and earlydebug dump files.  */
+
+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);
+}
+
+/* Set dump_file to the debug dump file.  */
+
+void
+debuginfo_start (void)
+{
+  set_dump_file (debuginfo_dump_file);
+}
+
+/* Undo setting dump_file to the debug dump file.  */
+
+void
+debuginfo_stop (void)
+{
+  set_dump_file (NULL);
+}
+
+/* Set dump_file to the earlydebug dump file.  */
+
+void
+debuginfo_early_start (void)
+{
+  set_dump_file (debuginfo_early_dump_file);
+}
+
+/* Undo setting dump_file to the earlydebug dump file.  */
+
+void
+debuginfo_early_stop (void)
+{
+  set_dump_file (NULL);
+}
 
 /* Analyze the whole compilation unit once it is parsed completely.  */
 
@@ -2691,7 +2774,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/doc/invoke.texi b/gcc/doc/invoke.texi
index f8287153be1..99849ec6467 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -566,6 +566,7 @@ Objective-C and Objective-C++ Dialects}.
 -fdisable-rtl-@var{pass-name}=@var{range-list} @gol
 -fdisable-tree-@var{pass_name} @gol
 -fdisable-tree-@var{pass-name}=@var{range-list} @gol
+-fdump-debug -fdump-earlydebug @gol
 -fdump-noaddr  -fdump-unnumbered  -fdump-unnumbered-links @gol
 -fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
 -fdump-final-insns@r{[}=@var{file}@r{]} @gol
@@ -13777,6 +13778,16 @@ Just generate RTL for a function instead of compiling it.  Usually used
 with @option{-fdump-rtl-expand}.
 @end table
 
+@item -fdump-debug
+@opindex fdump-debug
+Dump debugging information generated during the debug
+generation phase.
+
+@item -fdump-earlydebug
+@opindex fdump-earlydebug
+Dump debugging information generated during the early debug
+generation phase.
+
 @item -fdump-noaddr
 @opindex fdump-noaddr
 When doing debugging dumps, suppress address output.  This makes it more
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ffb332a358d..fb71ff349fa 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -31112,7 +31112,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;
@@ -31193,6 +31193,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);
 
@@ -31888,6 +31894,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;
     }
 
@@ -31965,6 +31976,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..0e4298ad3d7 100644
--- a/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
+++ b/gcc/testsuite/gcc.c-torture/unsorted/dump-noaddr.x
@@ -11,10 +11,10 @@ proc dump_compare { src options } {
     foreach option $option_list {
 	file delete -force $tmpdir/dump1
 	file mkdir $tmpdir/dump1
-	c-torture-compile $src "$option $options -dumpbase dump1/$dumpbase -DMASK=1 -x c --param ggc-min-heapsize=1 -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr"
+	c-torture-compile $src "$option $options -dumpbase dump1/$dumpbase -DMASK=1 -x c --param ggc-min-heapsize=1 -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr -gno-record-gcc-switches"
 	file delete -force $tmpdir/dump2
 	file mkdir $tmpdir/dump2
-	c-torture-compile $src "$option $options -dumpbase dump2/$dumpbase -DMASK=2 -x c -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr"
+	c-torture-compile $src "$option $options -dumpbase dump2/$dumpbase -DMASK=2 -x c -fdump-ipa-all -fdump-rtl-all -fdump-tree-all -fdump-noaddr -gno-record-gcc-switches"
 	foreach dump1 [lsort [glob -nocomplain $tmpdir/dump1/*]] {
 	    set dump2 "$tmpdir/dump2/[file tail $dump1]"
 	    set dumptail "gcc.c-torture/unsorted/[file tail $dump1]"
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 2789d71b24f..9fb83d4e43f 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.  */
@@ -1187,6 +1189,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 ();
 }
 
@@ -2081,6 +2084,7 @@ finalize (bool no_backend)
   if (!no_backend)
     {
       statistics_fini ();
+      debuginfo_fini ();
 
       g->get_passes ()->finish_optimization_passes ();
 
@@ -2158,6 +2162,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);

Patch

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);