diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 70b635c3488a93b026b2ce0371b56f8be49cab3d..d20527b2c19307b493cac6dce79db5f008a106af 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -362,6 +362,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   dbxout_end_block,
   debug_true_const_tree,	         /* ignore_block */
   dbxout_source_line,		         /* source_line */
+  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
   dbxout_begin_prologue,	         /* begin_prologue */
   debug_nothing_int_charstar,	         /* end_prologue */
   debug_nothing_int_charstar,	         /* begin_epilogue */
@@ -409,6 +410,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   xcoffout_end_block,
   debug_true_const_tree,	         /* ignore_block */
   xcoffout_source_line,
+  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
   xcoffout_begin_prologue,	         /* begin_prologue */
   debug_nothing_int_charstar,	         /* end_prologue */
   debug_nothing_int_charstar,	         /* begin_epilogue */
diff --git a/gcc/debug.c b/gcc/debug.c
index 0a7fcfa80cf3bebd82469dea82a3368caa9450c5..39add0d0b3909304fbb8e43fcd6fce3d0ca0399b 100644
--- a/gcc/debug.c
+++ b/gcc/debug.c
@@ -36,6 +36,7 @@ const struct gcc_debug_hooks do_nothing_debug_hooks =
   debug_nothing_int_int,	         /* end_block */
   debug_true_const_tree,	         /* ignore_block */
   debug_nothing_int_int_charstar_int_bool, /* source_line */
+  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
   debug_nothing_int_int_charstar,	 /* begin_prologue */
   debug_nothing_int_charstar,	         /* end_prologue */
   debug_nothing_int_charstar,	         /* begin_epilogue */
diff --git a/gcc/debug.h b/gcc/debug.h
index cd265ffbc99b548f824a53211078d8fc511d0014..ad45ea5374bf4956a7a87dec97fc25d970339f95 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -73,6 +73,10 @@ struct gcc_debug_hooks
   void (* source_line) (unsigned int line, unsigned int column,
 			const char *file, int discriminator, bool is_stmt);
 
+  /* Record a source file location for a DECL_IGNORED_P function.  */
+  void (* set_ignored_loc) (unsigned int line, unsigned int column,
+			    const char *file);
+
   /* Called at start of prologue code.  LINE is the first line in the
      function.  */
   void (* begin_prologue) (unsigned int line, unsigned int column,
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 5b819ab1a923b0045f23de28376e52bd962749c1..871362b5d0c7ae2e14a4c6986cf2f51fb81c8369 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -259,13 +259,21 @@ static GTY(()) int dw2_string_counter;
 /* True if the compilation unit places functions in more than one section.  */
 static GTY(()) bool have_multiple_function_sections = false;
 
-/* Whether the default text and cold text sections have been used at all.  */
-static GTY(()) bool text_section_used = false;
-static GTY(()) bool cold_text_section_used = false;
-
 /* The default cold text section.  */
 static GTY(()) section *cold_text_section;
 
+/* True if currently in text section.  */
+static GTY(()) bool in_text_section_p = false;
+
+/* Last debug-on location in corresponding section.  */
+static GTY(()) const char *last_text_label;
+static GTY(()) const char *last_cold_label;
+
+/* Mark debug-on/off locations per section.
+   NULL means the section is not used at all.  */
+static GTY(()) vec<const char *, va_gc> *switch_text_ranges;
+static GTY(()) vec<const char *, va_gc> *switch_cold_ranges;
+
 /* The DIE for C++14 'auto' in a function return type.  */
 static GTY(()) dw_die_ref auto_die;
 
@@ -275,7 +283,6 @@ static GTY(()) dw_die_ref decltype_auto_die;
 /* Forward declarations for functions defined in this file.  */
 
 static void output_call_frame_info (int);
-static void dwarf2out_note_section_used (void);
 
 /* Personality decl of current unit.  Used only when assembler does not support
    personality CFI.  */
@@ -1107,6 +1114,8 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
   fde->dw_fde_current_label = dup_label;
   fde->in_std_section = (fnsec == text_section
 			 || (cold_text_section && fnsec == cold_text_section));
+  fde->ignored_debug = DECL_IGNORED_P (current_function_decl);
+  in_text_section_p = fnsec == text_section;
 
   /* We only want to output line number information for the genuine dwarf2
      prologue case, not the eh frame case.  */
@@ -1174,6 +1183,59 @@ dwarf2out_vms_begin_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   fde->dw_fde_vms_begin_epilogue = xstrdup (label);
 }
 
+/* Mark the ranges of non-debug subsections in the std text sections.  */
+
+static void
+mark_ignored_debug_section (dw_fde_ref fde, bool second)
+{
+  bool std_section;
+  const char *begin_label, *end_label;
+  const char **last_end_label;
+  vec<const char *, va_gc> **switch_ranges;
+
+  if (second)
+    {
+      std_section = fde->second_in_std_section;
+      begin_label = fde->dw_fde_second_begin;
+      end_label   = fde->dw_fde_second_end;
+    }
+  else
+    {
+      std_section = fde->in_std_section;
+      begin_label = fde->dw_fde_begin;
+      end_label   = fde->dw_fde_end;
+    }
+
+  if (!std_section)
+    return;
+
+  if (in_text_section_p)
+    {
+      last_end_label = &last_text_label;
+      switch_ranges  = &switch_text_ranges;
+    }
+  else
+    {
+      last_end_label = &last_cold_label;
+      switch_ranges  = &switch_cold_ranges;
+    }
+
+  if (fde->ignored_debug)
+    {
+      if (*switch_ranges && !(vec_safe_length (*switch_ranges) & 1))
+	vec_safe_push (*switch_ranges, *last_end_label);
+    }
+  else
+    {
+      *last_end_label = end_label;
+
+      if (!*switch_ranges)
+	vec_alloc (*switch_ranges, 16);
+      else if (vec_safe_length (*switch_ranges) & 1)
+	vec_safe_push (*switch_ranges, begin_label);
+    }
+}
+
 /* Output a marker (i.e. a label) for the absolute end of the generated code
    for a function definition.  This gets called *after* the epilogue code has
    been generated.  */
@@ -1200,6 +1262,8 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
   gcc_assert (fde != NULL);
   if (fde->dw_fde_second_begin == NULL)
     fde->dw_fde_end = xstrdup (label);
+
+  mark_ignored_debug_section (fde, fde->dw_fde_second_begin != NULL);
 }
 
 void
@@ -1214,18 +1278,6 @@ dwarf2out_frame_finish (void)
     output_call_frame_info (1);
 }
 
-/* Note that the current function section is being used for code.  */
-
-static void
-dwarf2out_note_section_used (void)
-{
-  section *sec = current_function_section ();
-  if (sec == text_section)
-    text_section_used = true;
-  else if (sec == cold_text_section)
-    cold_text_section_used = true;
-}
-
 static void var_location_switch_text_section (void);
 static void set_cur_line_info_table (section *);
 
@@ -1254,13 +1306,11 @@ dwarf2out_switch_text_section (void)
     }
   have_multiple_function_sections = true;
 
-  /* There is no need to mark used sections when not debugging.  */
-  if (cold_text_section != NULL)
-    dwarf2out_note_section_used ();
-
   if (dwarf2out_do_cfi_asm ())
     fprintf (asm_out_file, "\t.cfi_endproc\n");
 
+  mark_ignored_debug_section (fde, false);
+
   /* Now do the real section switch.  */
   sect = current_function_section ();
   switch_to_section (sect);
@@ -1268,6 +1318,7 @@ dwarf2out_switch_text_section (void)
   fde->second_in_std_section
     = (sect == text_section
        || (cold_text_section && sect == cold_text_section));
+  in_text_section_p = sect == text_section;
 
   if (dwarf2out_do_cfi_asm ())
     dwarf2out_do_cfi_startproc (true);
@@ -2801,6 +2852,7 @@ static void dwarf2out_function_decl (tree);
 static void dwarf2out_begin_block (unsigned, unsigned);
 static void dwarf2out_end_block (unsigned, unsigned);
 static bool dwarf2out_ignore_block (const_tree);
+static void dwarf2out_set_ignored_loc (unsigned, unsigned, const char *);
 static void dwarf2out_early_global_decl (tree);
 static void dwarf2out_late_global_decl (tree);
 static void dwarf2out_type_decl (tree, int);
@@ -2836,6 +2888,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks =
   dwarf2out_end_block,
   dwarf2out_ignore_block,
   dwarf2out_source_line,
+  dwarf2out_set_ignored_loc,
   dwarf2out_begin_prologue,
 #if VMS_DEBUGGING_INFO
   dwarf2out_vms_end_prologue,
@@ -2885,6 +2938,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
   debug_nothing_int_int,	         /* end_block */
   debug_true_const_tree,	         /* ignore_block */
   dwarf2out_source_line,		 /* source_line */
+  debug_nothing_int_int_charstar,	 /* set_ignored_loc */
   debug_nothing_int_int_charstar,	 /* begin_prologue */
   debug_nothing_int_charstar,	         /* end_prologue */
   debug_nothing_int_charstar,	         /* begin_epilogue */
@@ -9756,10 +9810,12 @@ size_of_aranges (void)
   size = DWARF_ARANGES_HEADER_SIZE;
 
   /* Count the address/length pair for this compilation unit.  */
-  if (text_section_used)
-    size += 2 * DWARF2_ADDR_SIZE;
-  if (cold_text_section_used)
-    size += 2 * DWARF2_ADDR_SIZE;
+  if (switch_text_ranges)
+    size += 2 * DWARF2_ADDR_SIZE
+	    * (vec_safe_length (switch_text_ranges) / 2 + 1);
+  if (switch_cold_ranges)
+    size += 2 * DWARF2_ADDR_SIZE
+	    * (vec_safe_length (switch_cold_ranges) / 2 + 1);
   if (have_multiple_function_sections)
     {
       unsigned fde_idx;
@@ -9767,7 +9823,7 @@ size_of_aranges (void)
 
       FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
 	{
-	  if (DECL_IGNORED_P (fde->decl))
+	  if (fde->ignored_debug)
 	    continue;
 	  if (!fde->in_std_section)
 	    size += 2 * DWARF2_ADDR_SIZE;
@@ -11713,18 +11769,52 @@ output_aranges (void)
      the address may end up as 0 if the section is discarded by ld
      --gc-sections, leaving an invalid (0, 0) entry that can be
      confused with the terminator.  */
-  if (text_section_used)
+  if (switch_text_ranges)
     {
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address");
-      dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label,
-			    text_section_label, "Length");
+      const char *prev_loc = text_section_label;
+      const char *loc;
+      unsigned idx;
+
+      FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc)
+	if (prev_loc)
+	  {
+	    dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address");
+	    dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length");
+	    prev_loc = NULL;
+	  }
+	else
+	  prev_loc = loc;
+
+      if (prev_loc)
+	{
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address");
+	  dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label,
+				prev_loc, "Length");
+	}
     }
-  if (cold_text_section_used)
+
+  if (switch_cold_ranges)
     {
-      dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label,
-			   "Address");
-      dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label,
-			    cold_text_section_label, "Length");
+      const char *prev_loc = cold_text_section_label;
+      const char *loc;
+      unsigned idx;
+
+      FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc)
+	if (prev_loc)
+	  {
+	    dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address");
+	    dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length");
+	    prev_loc = NULL;
+	  }
+	else
+	  prev_loc = loc;
+
+      if (prev_loc)
+	{
+	  dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address");
+	  dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label,
+				prev_loc, "Length");
+	}
     }
 
   if (have_multiple_function_sections)
@@ -11734,7 +11824,7 @@ output_aranges (void)
 
       FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
 	{
-	  if (DECL_IGNORED_P (fde->decl))
+	  if (fde->ignored_debug)
 	    continue;
 	  if (!fde->in_std_section)
 	    {
@@ -28020,7 +28110,6 @@ dwarf2out_begin_function (tree fun)
       switch_to_section (sec);
     }
 
-  dwarf2out_note_section_used ();
   call_site_count = 0;
   tail_call_site_count = 0;
 
@@ -28323,6 +28412,20 @@ dwarf2out_source_line (unsigned int line, unsigned int column,
   table->in_use = true;
 }
 
+/* Record a source file location for a DECL_IGNORED_P function.  */
+
+static void
+dwarf2out_set_ignored_loc (unsigned int line, unsigned int column,
+			   const char *filename)
+{
+  dw_fde_ref fde = cfun->fde;
+
+  fde->ignored_debug = false;
+  set_cur_line_info_table (function_section (fde->decl));
+
+  dwarf2out_source_line (line, column, filename, 0, true);
+}
+
 /* Record the beginning of a new source file.  */
 
 static void
@@ -31760,30 +31863,68 @@ dwarf2out_finish (const char *filename)
 
   /* We can only use the low/high_pc attributes if all of the code was
      in .text.  */
-  if (!have_multiple_function_sections 
+  if ((!have_multiple_function_sections
+       && vec_safe_length (switch_text_ranges) < 2)
       || (dwarf_version < 3 && dwarf_strict))
     {
+      const char *end_label = text_end_label;
+      if (vec_safe_length (switch_text_ranges) == 1)
+	end_label = (*switch_text_ranges)[0];
       /* Don't add if the CU has no associated code.  */
-      if (text_section_used)
-        add_AT_low_high_pc (main_comp_unit_die, text_section_label,
-                            text_end_label, true);
+      if (switch_text_ranges)
+	add_AT_low_high_pc (main_comp_unit_die, text_section_label,
+			    end_label, true);
     }
   else
     {
       unsigned fde_idx;
       dw_fde_ref fde;
       bool range_list_added = false;
+      if (switch_text_ranges)
+	{
+	  const char *prev_loc = text_section_label;
+	  const char *loc;
+	  unsigned idx;
+
+	  FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc)
+	    if (prev_loc)
+	      {
+		add_ranges_by_labels (main_comp_unit_die, prev_loc,
+				      loc, &range_list_added, true);
+		prev_loc = NULL;
+	      }
+	    else
+	      prev_loc = loc;
 
-      if (text_section_used)
-        add_ranges_by_labels (main_comp_unit_die, text_section_label,
-                              text_end_label, &range_list_added, true);
-      if (cold_text_section_used)
-        add_ranges_by_labels (main_comp_unit_die, cold_text_section_label,
-                              cold_end_label, &range_list_added, true);
+	  if (prev_loc)
+	    add_ranges_by_labels (main_comp_unit_die, prev_loc,
+				  text_end_label, &range_list_added, true);
+	}
+
+      if (switch_cold_ranges)
+	{
+	  const char *prev_loc = cold_text_section_label;
+	  const char *loc;
+	  unsigned idx;
+
+	  FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc)
+	    if (prev_loc)
+	      {
+		add_ranges_by_labels (main_comp_unit_die, prev_loc,
+				      loc, &range_list_added, true);
+		prev_loc = NULL;
+	      }
+	    else
+	      prev_loc = loc;
+
+	  if (prev_loc)
+	    add_ranges_by_labels (main_comp_unit_die, prev_loc,
+				  cold_end_label, &range_list_added, true);
+	}
 
       FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde)
 	{
-	  if (DECL_IGNORED_P (fde->decl))
+	  if (fde->ignored_debug)
 	    continue;
 	  if (!fde->in_std_section)
             add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_begin,
@@ -32657,9 +32798,12 @@ dwarf2out_c_finalize (void)
   skeleton_debug_str_hash = NULL;
   dw2_string_counter = 0;
   have_multiple_function_sections = false;
-  text_section_used = false;
-  cold_text_section_used = false;
+  in_text_section_p = false;
   cold_text_section = NULL;
+  last_text_label = NULL;
+  last_cold_label = NULL;
+  switch_text_ranges = NULL;
+  switch_cold_ranges = NULL;
   current_unit_personality = NULL;
 
   early_dwarf = false;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 76a9c0a39a298eff4fd0150eb24eb83735524e23..54b6343704c72fdfad83665ea007354b730b3f93 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -114,6 +114,8 @@ struct GTY(()) dw_fde_node {
      hard frame pointer register should be emitted only on the latter
      instruction.  */
   unsigned rule18 : 1;
+  /* True if this function is to be ignored by debugger.  */
+  unsigned ignored_debug : 1;
 };
 
 
diff --git a/gcc/final.c b/gcc/final.c
index ba4285ddf14dc922cabe10fc82e4778d3fe32dce..e0a70fcd830b9c40f341a9e85ae3f6196ea64707 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1724,6 +1724,9 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen,
   if (!dwarf2_debug_info_emitted_p (current_function_decl))
     dwarf2out_begin_prologue (0, 0, NULL);
 
+  if (DECL_IGNORED_P (current_function_decl) && last_linenum && last_filename)
+    debug_hooks->set_ignored_loc (last_linenum, last_columnnum, last_filename);
+
 #ifdef LEAF_REG_REMAP
   if (crtl->uses_only_leaf_regs)
     leaf_renumber_regs (first);
@@ -2187,6 +2190,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 
 	  in_cold_section_p = !in_cold_section_p;
 
+	  gcc_checking_assert (in_cold_section_p);
 	  if (in_cold_section_p)
 	    cold_function_name
 	      = clone_function_name (current_function_decl, "cold");
@@ -2200,6 +2204,10 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
 	    }
 	  else if (!DECL_IGNORED_P (current_function_decl))
 	    debug_hooks->switch_text_section ();
+	  if (DECL_IGNORED_P (current_function_decl) && last_linenum
+	      && last_filename)
+	    debug_hooks->set_ignored_loc (last_linenum, last_columnnum,
+					  last_filename);
 
 	  switch_to_section (current_function_section ());
 	  targetm.asm_out.function_switched_text_sections (asm_out_file,
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index 4d11692e34cb509e65414c8a352ef59d71859b64..1b09f0da94ff33c37cad8839e28b834189d16040 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1517,6 +1517,12 @@ gt_ggc_mx (const char *& x)
   gt_ggc_m_S (x);
 }
 
+void
+gt_ggc_mx (char *& x)
+{
+  gt_ggc_m_S (x);
+}
+
 void
 gt_ggc_mx (unsigned char *& x)
 {
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index e4d79b0dca096488ab5bad1f7c61ce7cef4fe26b..2f21466af245d282e6cc9d4a10e1b7495209f29b 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -205,6 +205,12 @@ gt_pch_nx (const char *& x)
   gt_pch_n_S (x);
 }
 
+void
+gt_pch_nx (char *& x)
+{
+  gt_pch_n_S (x);
+}
+
 void
 gt_pch_nx (unsigned char *& x)
 {
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index c226bc69c8559e49a5b32dc625e159f38300dc65..05fadce075e5573f50a45b492d4dde30cbaddb79 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -188,6 +188,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks
    vmsdbgout_end_block,
    vmsdbgout_ignore_block,
    vmsdbgout_source_line,
+   debug_nothing_int_int_charstar, /* set_ignored_loc */
    vmsdbgout_begin_prologue,
    vmsdbgout_end_prologue,
    vmsdbgout_begin_epilogue,