Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine
@ 2025-09-07 19:29 Tom Tromey
  2025-09-07 19:29 ` [PATCH 1/7] Move lnp_state_machine to new file Tom Tromey
                   ` (7 more replies)
  0 siblings, 8 replies; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This started with a patch to shrink dwarf2/read.c a bit, by moving
lnp_state_machine to its own file.  Then I proceeded to clean up that
code a tiny bit.

Regression tested on x86-64 Fedora 40.

Signed-off-by: Tom Tromey <tom@tromey.com>
---
Tom Tromey (7):
      Move lnp_state_machine to new file
      Move compute_include_file_name earlier
      Boolify line-program.c
      Change dwarf_record_line_p to be a method
      Add m_builder member to lnp_state_machine
      Change dwarf_finish_line to be a method
      Change dwarf_record_line_1 to be a method

 gdb/Makefile.in           |   1 +
 gdb/dwarf2/line-program.c | 722 +++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/line-program.h |  47 +++
 gdb/dwarf2/read.c         | 901 ++++------------------------------------------
 gdb/dwarf2/read.h         |  31 ++
 5 files changed, 874 insertions(+), 828 deletions(-)
---
base-commit: 46ada32fc979550ad4f46792b74c182bb7232aeb
change-id: 20250907-breakpoint-cu-expand-852f7e832aaa

Best regards,
-- 
Tom Tromey <tom@tromey.com>


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 16:04   ` Simon Marchi
  2025-09-07 19:29 ` [PATCH 2/7] Move compute_include_file_name earlier Tom Tromey
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This patch moves lnp_state_machine and some supporting code to a new
file, dwarf2/line-program.c.  The main benefit of this is shrinking
dwarf2/read.c a bit.
---
 gdb/Makefile.in           |   1 +
 gdb/dwarf2/line-program.c | 731 ++++++++++++++++++++++++++++++++++++++++++++
 gdb/dwarf2/line-program.h |  47 +++
 gdb/dwarf2/read.c         | 757 +---------------------------------------------
 gdb/dwarf2/read.h         |  31 ++
 5 files changed, 814 insertions(+), 753 deletions(-)

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 7654fb1aa04465e570b2e06f9a223b95448b0ca2..d7f8b95cae736255d4d26bc6c85cb8e22675c9f1 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -1910,6 +1910,7 @@ DWARF2_SRCS = \
 	dwarf2/index-write.c \
 	dwarf2/leb.c \
 	dwarf2/line-header.c \
+	dwarf2/line-program.c \
 	dwarf2/loc.c \
 	dwarf2/macro.c \
 	dwarf2/parent-map.c \
diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
new file mode 100644
index 0000000000000000000000000000000000000000..72bdd1f5a748ce228114105597b1e5a162254f69
--- /dev/null
+++ b/gdb/dwarf2/line-program.c
@@ -0,0 +1,731 @@
+/* DWARF 2 debugging format support for GDB.
+
+   Copyright (C) 1994-2025 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "dwarf2/line-program.h"
+#include "dwarf2/cu.h"
+#include "dwarf2/line-header.h"
+#include "dwarf2/read.h"
+#include "buildsym.h"
+#include "complaints.h"
+#include "filenames.h"
+#include "gdbarch.h"
+
+static void
+dwarf2_debug_line_missing_file_complaint ()
+{
+  complaint (_(".debug_line section has line data without a file"));
+}
+
+static void
+dwarf2_debug_line_missing_end_sequence_complaint ()
+{
+  complaint (_(".debug_line section has line "
+	       "program sequence without an end"));
+}
+
+/* State machine to track the state of the line number program.  */
+
+class lnp_state_machine
+{
+public:
+  /* Initialize a machine state for the start of a line number
+     program.  */
+  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
+
+  file_entry *current_file ()
+  {
+    /* lh->file_names is 0-based, but the file name numbers in the
+       statement program are 1-based.  */
+    return m_line_header->file_name_at (m_file);
+  }
+
+  /* Record the line in the state machine.  END_SEQUENCE is true if
+     we're processing the end of a sequence.  */
+  void record_line (bool end_sequence);
+
+  /* Check ADDRESS is -1, -2, or zero and less than UNRELOCATED_LOWPC, and if
+     true nop-out rest of the lines in this sequence.  */
+  void check_line_address (struct dwarf2_cu *cu,
+			   const gdb_byte *line_ptr,
+			   unrelocated_addr unrelocated_lowpc,
+			   unrelocated_addr address);
+
+  void handle_set_discriminator (unsigned int discriminator)
+  {
+    m_discriminator = discriminator;
+    m_line_has_non_zero_discriminator |= discriminator != 0;
+  }
+
+  /* Handle DW_LNE_set_address.  */
+  void handle_set_address (unrelocated_addr address)
+  {
+    m_op_index = 0;
+    m_address
+      = (unrelocated_addr) gdbarch_adjust_dwarf2_line (m_gdbarch,
+						       (CORE_ADDR) address,
+						       false);
+  }
+
+  /* Handle DW_LNS_advance_pc.  */
+  void handle_advance_pc (CORE_ADDR adjust);
+
+  /* Handle a special opcode.  */
+  void handle_special_opcode (unsigned char op_code);
+
+  /* Handle DW_LNS_advance_line.  */
+  void handle_advance_line (int line_delta)
+  {
+    advance_line (line_delta);
+  }
+
+  /* Handle DW_LNS_set_file.  */
+  void handle_set_file (file_name_index file);
+
+  /* Handle DW_LNS_negate_stmt.  */
+  void handle_negate_stmt ()
+  {
+    m_flags ^= LEF_IS_STMT;
+  }
+
+  /* Handle DW_LNS_const_add_pc.  */
+  void handle_const_add_pc ();
+
+  /* Handle DW_LNS_fixed_advance_pc.  */
+  void handle_fixed_advance_pc (CORE_ADDR addr_adj)
+  {
+    addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+    m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+    m_op_index = 0;
+  }
+
+  /* Handle DW_LNS_copy.  */
+  void handle_copy ()
+  {
+    record_line (false);
+    m_discriminator = 0;
+    m_flags &= ~LEF_PROLOGUE_END;
+    m_flags &= ~LEF_EPILOGUE_BEGIN;
+  }
+
+  /* Handle DW_LNE_end_sequence.  */
+  void handle_end_sequence ()
+  {
+    m_currently_recording_lines = true;
+  }
+
+  /* Handle DW_LNS_set_prologue_end.  */
+  void handle_set_prologue_end ()
+  {
+    m_flags |= LEF_PROLOGUE_END;
+  }
+
+  void handle_set_epilogue_begin ()
+  {
+    m_flags |= LEF_EPILOGUE_BEGIN;
+  }
+
+private:
+  /* Advance the line by LINE_DELTA.  */
+  void advance_line (int line_delta)
+  {
+    m_line += line_delta;
+
+    if (line_delta != 0)
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+  }
+
+  struct dwarf2_cu *m_cu;
+
+  gdbarch *m_gdbarch;
+
+  /* The line number header.  */
+  line_header *m_line_header;
+
+  /* These are part of the standard DWARF line number state machine,
+     and initialized according to the DWARF spec.  */
+
+  unsigned char m_op_index = 0;
+  /* The line table index of the current file.  */
+  file_name_index m_file = 1;
+  unsigned int m_line = 1;
+
+  /* These are initialized in the constructor.  */
+
+  unrelocated_addr m_address;
+  linetable_entry_flags m_flags;
+  unsigned int m_discriminator = 0;
+
+  /* Additional bits of state we need to track.  */
+
+  /* The last file a line number was recorded for.  */
+  struct subfile *m_last_subfile = NULL;
+
+  /* The address of the last line entry.  */
+  unrelocated_addr m_last_address;
+
+  /* Set to true when a previous line at the same address (using
+     m_last_address) had LEF_IS_STMT set in m_flags.  This is reset to false
+     when a line entry at a new address (m_address different to
+     m_last_address) is processed.  */
+  bool m_stmt_at_address = false;
+
+  /* When true, record the lines we decode.  */
+  bool m_currently_recording_lines = true;
+
+  /* The last line number that was recorded, used to coalesce
+     consecutive entries for the same line.  This can happen, for
+     example, when discriminators are present.  PR 17276.  */
+  unsigned int m_last_line = 0;
+  bool m_line_has_non_zero_discriminator = false;
+};
+
+void
+lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
+{
+  CORE_ADDR addr_adj = (((m_op_index + adjust)
+			 / m_line_header->maximum_ops_per_instruction)
+			* m_line_header->minimum_instruction_length);
+  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+  m_op_index = ((m_op_index + adjust)
+		% m_line_header->maximum_ops_per_instruction);
+}
+
+void
+lnp_state_machine::handle_special_opcode (unsigned char op_code)
+{
+  unsigned char adj_opcode = op_code - m_line_header->opcode_base;
+  unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
+  unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
+  CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
+			 / m_line_header->maximum_ops_per_instruction)
+			* m_line_header->minimum_instruction_length);
+  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+  m_op_index = ((m_op_index + adj_opcode_d)
+		% m_line_header->maximum_ops_per_instruction);
+
+  int line_delta = m_line_header->line_base + adj_opcode_r;
+  advance_line (line_delta);
+  record_line (false);
+  m_discriminator = 0;
+  m_flags &= ~LEF_PROLOGUE_END;
+  m_flags &= ~LEF_EPILOGUE_BEGIN;
+}
+
+void
+lnp_state_machine::handle_set_file (file_name_index file)
+{
+  m_file = file;
+
+  const file_entry *fe = current_file ();
+  if (fe == NULL)
+    dwarf2_debug_line_missing_file_complaint ();
+  else
+    {
+      m_line_has_non_zero_discriminator = m_discriminator != 0;
+      dwarf2_start_subfile (m_cu, *fe, *m_line_header);
+    }
+}
+
+void
+lnp_state_machine::handle_const_add_pc ()
+{
+  CORE_ADDR adjust
+    = (255 - m_line_header->opcode_base) / m_line_header->line_range;
+
+  CORE_ADDR addr_adj
+    = (((m_op_index + adjust)
+	/ m_line_header->maximum_ops_per_instruction)
+       * m_line_header->minimum_instruction_length);
+
+  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
+  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
+  m_op_index = ((m_op_index + adjust)
+		% m_line_header->maximum_ops_per_instruction);
+}
+
+/* Return non-zero if we should add LINE to the line number table.
+   LINE is the line to add, LAST_LINE is the last line that was added,
+   LAST_SUBFILE is the subfile for LAST_LINE.
+   LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
+   had a non-zero discriminator.
+
+   We have to be careful in the presence of discriminators.
+   E.g., for this line:
+
+     for (i = 0; i < 100000; i++);
+
+   clang can emit four line number entries for that one line,
+   each with a different discriminator.
+   See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
+
+   However, we want gdb to coalesce all four entries into one.
+   Otherwise the user could stepi into the middle of the line and
+   gdb would get confused about whether the pc really was in the
+   middle of the line.
+
+   Things are further complicated by the fact that two consecutive
+   line number entries for the same line is a heuristic used by gcc
+   to denote the end of the prologue.  So we can't just discard duplicate
+   entries, we have to be selective about it.  The heuristic we use is
+   that we only collapse consecutive entries for the same line if at least
+   one of those entries has a non-zero discriminator.  PR 17276.
+
+   Note: Addresses in the line number state machine can never go backwards
+   within one sequence, thus this coalescing is ok.  */
+
+static int
+dwarf_record_line_p (struct dwarf2_cu *cu,
+		     unsigned int line, unsigned int last_line,
+		     int line_has_non_zero_discriminator,
+		     struct subfile *last_subfile)
+{
+  if (cu->get_builder ()->get_current_subfile () != last_subfile)
+    return 1;
+  if (line != last_line)
+    return 1;
+  /* Same line for the same file that we've seen already.
+     As a last check, for pr 17276, only record the line if the line
+     has never had a non-zero discriminator.  */
+  if (!line_has_non_zero_discriminator)
+    return 1;
+  return 0;
+}
+
+/* Use the CU's builder to record line number LINE beginning at
+   address ADDRESS in the line table of subfile SUBFILE.  */
+
+static void
+dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
+		     unsigned int line, unrelocated_addr address,
+		     linetable_entry_flags flags,
+		     struct dwarf2_cu *cu)
+{
+  unrelocated_addr addr
+    = unrelocated_addr (gdbarch_addr_bits_remove (gdbarch,
+						  (CORE_ADDR) address));
+
+  if (cu != nullptr)
+    {
+      if (dwarf_line_debug)
+	gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
+		    line, lbasename (subfile->name.c_str ()),
+		    paddress (gdbarch, (CORE_ADDR) address));
+
+      cu->get_builder ()->record_line (subfile, line, addr, flags);
+    }
+}
+
+/* Subroutine of dwarf_decode_lines_1 to simplify it.
+   Mark the end of a set of line number records.
+   The arguments are the same as for dwarf_record_line_1.
+   If SUBFILE is NULL the request is ignored.  */
+
+static void
+dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
+		   unrelocated_addr address, struct dwarf2_cu *cu)
+{
+  if (subfile == NULL)
+    return;
+
+  if (dwarf_line_debug)
+    {
+      gdb_printf (gdb_stdlog,
+		  "Finishing current line, file %s, address %s\n",
+		  lbasename (subfile->name.c_str ()),
+		  paddress (gdbarch, (CORE_ADDR) address));
+    }
+
+  dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
+}
+
+void
+lnp_state_machine::record_line (bool end_sequence)
+{
+  if (dwarf_line_debug)
+    {
+      gdb_printf (gdb_stdlog,
+		  "Processing actual line %u: file %u,"
+		  " address %s, is_stmt %u, prologue_end %u,"
+		  " epilogue_begin %u, discrim %u%s\n",
+		  m_line, m_file,
+		  paddress (m_gdbarch, (CORE_ADDR) m_address),
+		  (m_flags & LEF_IS_STMT) != 0,
+		  (m_flags & LEF_PROLOGUE_END) != 0,
+		  (m_flags & LEF_EPILOGUE_BEGIN) != 0,
+		  m_discriminator,
+		  (end_sequence ? "\t(end sequence)" : ""));
+    }
+
+  file_entry *fe = current_file ();
+
+  if (fe == NULL)
+    dwarf2_debug_line_missing_file_complaint ();
+  /* For now we ignore lines not starting on an instruction boundary.
+     But not when processing end_sequence for compatibility with the
+     previous version of the code.  */
+  else if (m_op_index == 0 || end_sequence)
+    {
+      /* When we switch files we insert an end maker in the first file,
+	 switch to the second file and add a new line entry.  The
+	 problem is that the end marker inserted in the first file will
+	 discard any previous line entries at the same address.  If the
+	 line entries in the first file are marked as is-stmt, while
+	 the new line in the second file is non-stmt, then this means
+	 the end marker will discard is-stmt lines so we can have a
+	 non-stmt line.  This means that there are less addresses at
+	 which the user can insert a breakpoint.
+
+	 To improve this we track the last address in m_last_address,
+	 and whether we have seen an is-stmt at this address.  Then
+	 when switching files, if we have seen a stmt at the current
+	 address, and we are switching to create a non-stmt line, then
+	 discard the new line.  */
+      bool file_changed
+	= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+      bool ignore_this_line
+	= ((file_changed && !end_sequence && m_last_address == m_address
+	    && ((m_flags & LEF_IS_STMT) == 0)
+	    && m_stmt_at_address)
+	   || (!end_sequence && m_line == 0));
+
+      if ((file_changed && !ignore_this_line) || end_sequence)
+	{
+	  dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
+			     m_currently_recording_lines ? m_cu : nullptr);
+	}
+
+      if (!end_sequence && !ignore_this_line)
+	{
+	  linetable_entry_flags lte_flags = m_flags;
+	  if (m_cu->producer_is_codewarrior ())
+	    lte_flags |= LEF_IS_STMT;
+
+	  if (dwarf_record_line_p (m_cu, m_line, m_last_line,
+				   m_line_has_non_zero_discriminator,
+				   m_last_subfile))
+	    {
+	      buildsym_compunit *builder = m_cu->get_builder ();
+	      dwarf_record_line_1 (m_gdbarch,
+				   builder->get_current_subfile (),
+				   m_line, m_address, lte_flags,
+				   m_currently_recording_lines ? m_cu : nullptr);
+
+	      m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
+	      m_last_line = m_line;
+	    }
+	}
+    }
+
+  /* Track whether we have seen any IS_STMT true at m_address in case we
+     have multiple line table entries all at m_address.  */
+  if (m_last_address != m_address)
+    {
+      m_stmt_at_address = false;
+      m_last_address = m_address;
+    }
+  m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
+}
+
+lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
+				      line_header *lh)
+  : m_cu (cu),
+    m_gdbarch (arch),
+    m_line_header (lh),
+    /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as
+       if there was a line entry for it so that the backend has a
+       chance to adjust it and also record it in case it needs it.
+       This is currently used by MIPS code,
+       cf. `mips_adjust_dwarf2_line'.  */
+    m_address ((unrelocated_addr) gdbarch_adjust_dwarf2_line (arch, 0, 0)),
+    m_flags (lh->default_is_stmt ? LEF_IS_STMT : (linetable_entry_flags) 0),
+    m_last_address (m_address)
+{
+}
+
+void
+lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
+				       const gdb_byte *line_ptr,
+				       unrelocated_addr unrelocated_lowpc,
+				       unrelocated_addr address)
+{
+  /* Linkers resolve a symbolic relocation referencing a GC'd function to 0,
+     -1 or -2 (-2 is used by certain lld versions, see
+     https://github.com/llvm/llvm-project/commit/e618ccbf431f6730edb6d1467a127c3a52fd57f7).
+     If ADDRESS is 0, ignoring the opcode will err if the text section is
+     located at 0x0.  In this case, additionally check that if
+     ADDRESS < UNRELOCATED_LOWPC.  */
+
+  if ((address == (unrelocated_addr) 0 && address < unrelocated_lowpc)
+      || address == (unrelocated_addr) -1
+      || address == (unrelocated_addr) -2)
+    {
+      /* This line table is for a function which has been
+	 GCd by the linker.  Ignore it.  PR gdb/12528 */
+
+      struct objfile *objfile = cu->per_objfile->objfile;
+      long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
+
+      complaint (_(".debug_line address at offset 0x%lx is 0 [in module %s]"),
+		 line_offset, objfile_name (objfile));
+      m_currently_recording_lines = false;
+      /* Note: m_currently_recording_lines is left as false until we see
+	 DW_LNE_end_sequence.  */
+    }
+}
+
+/* Subroutine of dwarf_decode_lines to simplify it.
+   Process the line number information in LH.  */
+
+static void
+dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
+		      unrelocated_addr lowpc)
+{
+  const gdb_byte *line_ptr, *extended_end;
+  const gdb_byte *line_end;
+  unsigned int bytes_read, extended_len;
+  unsigned char op_code, extended_op;
+  struct objfile *objfile = cu->per_objfile->objfile;
+  bfd *abfd = objfile->obfd.get ();
+  struct gdbarch *gdbarch = objfile->arch ();
+
+  line_ptr = lh->statement_program_start;
+  line_end = lh->statement_program_end;
+
+  /* Read the statement sequences until there's nothing left.  */
+  while (line_ptr < line_end)
+    {
+      /* The DWARF line number program state machine.  Reset the state
+	 machine at the start of each sequence.  */
+      lnp_state_machine state_machine (cu, gdbarch, lh);
+      bool end_sequence = false;
+
+      /* Start a subfile for the current file of the state
+	 machine.  */
+      const file_entry *fe = state_machine.current_file ();
+
+      if (fe != NULL)
+	dwarf2_start_subfile (cu, *fe, *lh);
+
+      /* Decode the table.  */
+      while (line_ptr < line_end && !end_sequence)
+	{
+	  op_code = read_1_byte (abfd, line_ptr);
+	  line_ptr += 1;
+
+	  if (op_code >= lh->opcode_base)
+	    {
+	      /* Special opcode.  */
+	      state_machine.handle_special_opcode (op_code);
+	    }
+	  else switch (op_code)
+	    {
+	    case DW_LNS_extended_op:
+	      extended_len = read_unsigned_leb128 (abfd, line_ptr,
+						   &bytes_read);
+	      line_ptr += bytes_read;
+	      extended_end = line_ptr + extended_len;
+	      extended_op = read_1_byte (abfd, line_ptr);
+	      line_ptr += 1;
+	      if (DW_LNE_lo_user <= extended_op
+		  && extended_op <= DW_LNE_hi_user)
+		{
+		  /* Vendor extension, ignore.  */
+		  line_ptr = extended_end;
+		  break;
+		}
+	      switch (extended_op)
+		{
+		case DW_LNE_end_sequence:
+		  state_machine.handle_end_sequence ();
+		  end_sequence = true;
+		  break;
+		case DW_LNE_set_address:
+		  {
+		    unrelocated_addr address
+		      = cu->header.read_address (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+
+		    state_machine.check_line_address (cu, line_ptr, lowpc,
+						      address);
+		    state_machine.handle_set_address (address);
+		  }
+		  break;
+		case DW_LNE_define_file:
+		  {
+		    const char *cur_file;
+		    unsigned int mod_time, length;
+		    dir_index dindex;
+
+		    cur_file = read_direct_string (abfd, line_ptr,
+						   &bytes_read);
+		    line_ptr += bytes_read;
+		    dindex = (dir_index)
+		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+		    mod_time =
+		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+		    length =
+		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+		    lh->add_file_name (cur_file, dindex, mod_time, length);
+		  }
+		  break;
+		case DW_LNE_set_discriminator:
+		  {
+		    /* The discriminator is not interesting to the
+		       debugger; just ignore it.  We still need to
+		       check its value though:
+		       if there are consecutive entries for the same
+		       (non-prologue) line we want to coalesce them.
+		       PR 17276.  */
+		    unsigned int discr
+		      = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+
+		    state_machine.handle_set_discriminator (discr);
+		  }
+		  break;
+		default:
+		  complaint (_("mangled .debug_line section"));
+		  return;
+		}
+	      /* Make sure that we parsed the extended op correctly.  If e.g.
+		 we expected a different address size than the producer used,
+		 we may have read the wrong number of bytes.  */
+	      if (line_ptr != extended_end)
+		{
+		  complaint (_("mangled .debug_line section"));
+		  return;
+		}
+	      break;
+	    case DW_LNS_copy:
+	      state_machine.handle_copy ();
+	      break;
+	    case DW_LNS_advance_pc:
+	      {
+		CORE_ADDR adjust
+		  = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		line_ptr += bytes_read;
+
+		state_machine.handle_advance_pc (adjust);
+	      }
+	      break;
+	    case DW_LNS_advance_line:
+	      {
+		int line_delta
+		  = read_signed_leb128 (abfd, line_ptr, &bytes_read);
+		line_ptr += bytes_read;
+
+		state_machine.handle_advance_line (line_delta);
+	      }
+	      break;
+	    case DW_LNS_set_file:
+	      {
+		file_name_index file
+		  = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
+							    &bytes_read);
+		line_ptr += bytes_read;
+
+		state_machine.handle_set_file (file);
+	      }
+	      break;
+	    case DW_LNS_set_column:
+	      (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+	      line_ptr += bytes_read;
+	      break;
+	    case DW_LNS_negate_stmt:
+	      state_machine.handle_negate_stmt ();
+	      break;
+	    case DW_LNS_set_basic_block:
+	      break;
+	    /* Add to the address register of the state machine the
+	       address increment value corresponding to special opcode
+	       255.  I.e., this value is scaled by the minimum
+	       instruction length since special opcode 255 would have
+	       scaled the increment.  */
+	    case DW_LNS_const_add_pc:
+	      state_machine.handle_const_add_pc ();
+	      break;
+	    case DW_LNS_fixed_advance_pc:
+	      {
+		CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
+		line_ptr += 2;
+
+		state_machine.handle_fixed_advance_pc (addr_adj);
+	      }
+	      break;
+	    case DW_LNS_set_prologue_end:
+	      state_machine.handle_set_prologue_end ();
+	      break;
+	    case DW_LNS_set_epilogue_begin:
+	      state_machine.handle_set_epilogue_begin ();
+	      break;
+	    default:
+	      {
+		/* Unknown standard opcode, ignore it.  */
+		int i;
+
+		for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
+		  {
+		    (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+		    line_ptr += bytes_read;
+		  }
+	      }
+	    }
+	}
+
+      if (!end_sequence)
+	dwarf2_debug_line_missing_end_sequence_complaint ();
+
+      /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
+	 in which case we still finish recording the last line).  */
+      state_machine.record_line (true);
+    }
+}
+
+/* See dwarf2/line-program.h.  */
+
+void
+dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
+		    unrelocated_addr lowpc, int decode_mapping)
+{
+  if (decode_mapping)
+    dwarf_decode_lines_1 (lh, cu, lowpc);
+
+  /* Make sure a symtab is created for every file, even files
+     which contain only variables (i.e. no code with associated
+     line numbers).  */
+  buildsym_compunit *builder = cu->get_builder ();
+  struct compunit_symtab *cust = builder->get_compunit_symtab ();
+
+  for (auto &fe : lh->file_names ())
+    {
+      dwarf2_start_subfile (cu, fe, *lh);
+      subfile *sf = builder->get_current_subfile ();
+
+      if (sf->symtab == nullptr)
+	sf->symtab = allocate_symtab (cust, sf->name.c_str (),
+				      sf->name_for_id.c_str ());
+
+      fe.symtab = sf->symtab;
+    }
+}
diff --git a/gdb/dwarf2/line-program.h b/gdb/dwarf2/line-program.h
new file mode 100644
index 0000000000000000000000000000000000000000..c84403253e635225d7c27d49a91dd1581fa0fa2e
--- /dev/null
+++ b/gdb/dwarf2/line-program.h
@@ -0,0 +1,47 @@
+/* DWARF 2 debugging format support for GDB.
+
+   Copyright (C) 1994-2025 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef GDB_DWARF2_LINE_PROGRAM_H
+#define GDB_DWARF2_LINE_PROGRAM_H
+
+/* Decode the Line Number Program (LNP) for the given line_header
+   structure and CU.  The actual information extracted and the type
+   of structures created from the LNP depends on the value of PST.
+
+   FND holds the CU file name and directory, if known.
+   It is used for relative paths in the line table.
+
+   NOTE: It is important that psymtabs have the same file name (via
+   strcmp) as the corresponding symtab.  Since the directory is not
+   used in the name of the symtab we don't use it in the name of the
+   psymtabs we create.  E.g. expand_line_sal requires this when
+   finding psymtabs to expand.  A good testcase for this is
+   mb-inline.exp.
+
+   LOWPC is the lowest address in CU (or 0 if not known).
+
+   Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
+   for its PC<->lines mapping information.  Otherwise only the filename
+   table is read in.  */
+
+extern void dwarf_decode_lines (struct line_header *lh,
+				struct dwarf2_cu *cu,
+				unrelocated_addr lowpc, int decode_mapping);
+
+#endif /* GDB_DWARF2_LINE_PROGRAM_H */
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 29650c577378f9165898de8fec399f72ffefae9d..efff522d9b36f70fb7f37d426ab744bb6d4085b3 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -38,6 +38,7 @@
 #include "dwarf2/index-cache.h"
 #include "dwarf2/leb.h"
 #include "dwarf2/line-header.h"
+#include "dwarf2/line-program.h"
 #include "dwarf2/dwz.h"
 #include "dwarf2/macro.h"
 #include "dwarf2/die.h"
@@ -787,13 +788,6 @@ static line_header_up dwarf_decode_line_header (sect_offset sect_off,
 						struct dwarf2_cu *cu,
 						const char *comp_dir);
 
-static void dwarf_decode_lines (struct line_header *,
-				struct dwarf2_cu *,
-				unrelocated_addr, int decode_mapping);
-
-static void dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
-				  const line_header &lh);
-
 static struct symbol *new_symbol (struct die_info *, struct type *,
 				  struct dwarf2_cu *, struct symbol * = NULL);
 
@@ -1062,19 +1056,6 @@ static void process_cu_includes (dwarf2_per_objfile *per_objfile);
 \f
 /* Various complaints about symbol reading that don't abort the process.  */
 
-static void
-dwarf2_debug_line_missing_file_complaint (void)
-{
-  complaint (_(".debug_line section has line data without a file"));
-}
-
-static void
-dwarf2_debug_line_missing_end_sequence_complaint (void)
-{
-  complaint (_(".debug_line section has line "
-	       "program sequence without an end"));
-}
-
 static void
 dwarf2_complex_location_expr_complaint (void)
 {
@@ -15759,9 +15740,9 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu)
     return follow_die_ref (die, spec_attr, spec_cu);
 }
 
-/* A convenience function to find the proper .debug_line section for a CU.  */
+/* See dwarf2/read.h.  */
 
-static struct dwarf2_section_info *
+struct dwarf2_section_info *
 get_debug_line_section (struct dwarf2_cu *cu)
 {
   struct dwarf2_section_info *section;
@@ -15881,739 +15862,9 @@ compute_include_file_name (const struct line_header *lh, const file_entry &fe,
   return include_name;
 }
 
-/* State machine to track the state of the line number program.  */
-
-class lnp_state_machine
-{
-public:
-  /* Initialize a machine state for the start of a line number
-     program.  */
-  lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch, line_header *lh);
-
-  file_entry *current_file ()
-  {
-    /* lh->file_names is 0-based, but the file name numbers in the
-       statement program are 1-based.  */
-    return m_line_header->file_name_at (m_file);
-  }
-
-  /* Record the line in the state machine.  END_SEQUENCE is true if
-     we're processing the end of a sequence.  */
-  void record_line (bool end_sequence);
-
-  /* Check ADDRESS is -1, -2, or zero and less than UNRELOCATED_LOWPC, and if
-     true nop-out rest of the lines in this sequence.  */
-  void check_line_address (struct dwarf2_cu *cu,
-			   const gdb_byte *line_ptr,
-			   unrelocated_addr unrelocated_lowpc,
-			   unrelocated_addr address);
-
-  void handle_set_discriminator (unsigned int discriminator)
-  {
-    m_discriminator = discriminator;
-    m_line_has_non_zero_discriminator |= discriminator != 0;
-  }
-
-  /* Handle DW_LNE_set_address.  */
-  void handle_set_address (unrelocated_addr address)
-  {
-    m_op_index = 0;
-    m_address
-      = (unrelocated_addr) gdbarch_adjust_dwarf2_line (m_gdbarch,
-						       (CORE_ADDR) address,
-						       false);
-  }
-
-  /* Handle DW_LNS_advance_pc.  */
-  void handle_advance_pc (CORE_ADDR adjust);
-
-  /* Handle a special opcode.  */
-  void handle_special_opcode (unsigned char op_code);
-
-  /* Handle DW_LNS_advance_line.  */
-  void handle_advance_line (int line_delta)
-  {
-    advance_line (line_delta);
-  }
-
-  /* Handle DW_LNS_set_file.  */
-  void handle_set_file (file_name_index file);
-
-  /* Handle DW_LNS_negate_stmt.  */
-  void handle_negate_stmt ()
-  {
-    m_flags ^= LEF_IS_STMT;
-  }
-
-  /* Handle DW_LNS_const_add_pc.  */
-  void handle_const_add_pc ();
-
-  /* Handle DW_LNS_fixed_advance_pc.  */
-  void handle_fixed_advance_pc (CORE_ADDR addr_adj)
-  {
-    addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
-    m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
-    m_op_index = 0;
-  }
-
-  /* Handle DW_LNS_copy.  */
-  void handle_copy ()
-  {
-    record_line (false);
-    m_discriminator = 0;
-    m_flags &= ~LEF_PROLOGUE_END;
-    m_flags &= ~LEF_EPILOGUE_BEGIN;
-  }
-
-  /* Handle DW_LNE_end_sequence.  */
-  void handle_end_sequence ()
-  {
-    m_currently_recording_lines = true;
-  }
-
-  /* Handle DW_LNS_set_prologue_end.  */
-  void handle_set_prologue_end ()
-  {
-    m_flags |= LEF_PROLOGUE_END;
-  }
-
-  void handle_set_epilogue_begin ()
-  {
-    m_flags |= LEF_EPILOGUE_BEGIN;
-  }
-
-private:
-  /* Advance the line by LINE_DELTA.  */
-  void advance_line (int line_delta)
-  {
-    m_line += line_delta;
-
-    if (line_delta != 0)
-      m_line_has_non_zero_discriminator = m_discriminator != 0;
-  }
-
-  struct dwarf2_cu *m_cu;
-
-  gdbarch *m_gdbarch;
-
-  /* The line number header.  */
-  line_header *m_line_header;
-
-  /* These are part of the standard DWARF line number state machine,
-     and initialized according to the DWARF spec.  */
-
-  unsigned char m_op_index = 0;
-  /* The line table index of the current file.  */
-  file_name_index m_file = 1;
-  unsigned int m_line = 1;
-
-  /* These are initialized in the constructor.  */
-
-  unrelocated_addr m_address;
-  linetable_entry_flags m_flags;
-  unsigned int m_discriminator = 0;
-
-  /* Additional bits of state we need to track.  */
-
-  /* The last file a line number was recorded for.  */
-  struct subfile *m_last_subfile = NULL;
-
-  /* The address of the last line entry.  */
-  unrelocated_addr m_last_address;
-
-  /* Set to true when a previous line at the same address (using
-     m_last_address) had LEF_IS_STMT set in m_flags.  This is reset to false
-     when a line entry at a new address (m_address different to
-     m_last_address) is processed.  */
-  bool m_stmt_at_address = false;
-
-  /* When true, record the lines we decode.  */
-  bool m_currently_recording_lines = true;
-
-  /* The last line number that was recorded, used to coalesce
-     consecutive entries for the same line.  This can happen, for
-     example, when discriminators are present.  PR 17276.  */
-  unsigned int m_last_line = 0;
-  bool m_line_has_non_zero_discriminator = false;
-};
-
-void
-lnp_state_machine::handle_advance_pc (CORE_ADDR adjust)
-{
-  CORE_ADDR addr_adj = (((m_op_index + adjust)
-			 / m_line_header->maximum_ops_per_instruction)
-			* m_line_header->minimum_instruction_length);
-  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
-  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
-  m_op_index = ((m_op_index + adjust)
-		% m_line_header->maximum_ops_per_instruction);
-}
-
-void
-lnp_state_machine::handle_special_opcode (unsigned char op_code)
-{
-  unsigned char adj_opcode = op_code - m_line_header->opcode_base;
-  unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
-  unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
-  CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
-			 / m_line_header->maximum_ops_per_instruction)
-			* m_line_header->minimum_instruction_length);
-  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
-  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
-  m_op_index = ((m_op_index + adj_opcode_d)
-		% m_line_header->maximum_ops_per_instruction);
-
-  int line_delta = m_line_header->line_base + adj_opcode_r;
-  advance_line (line_delta);
-  record_line (false);
-  m_discriminator = 0;
-  m_flags &= ~LEF_PROLOGUE_END;
-  m_flags &= ~LEF_EPILOGUE_BEGIN;
-}
-
-void
-lnp_state_machine::handle_set_file (file_name_index file)
-{
-  m_file = file;
-
-  const file_entry *fe = current_file ();
-  if (fe == NULL)
-    dwarf2_debug_line_missing_file_complaint ();
-  else
-    {
-      m_line_has_non_zero_discriminator = m_discriminator != 0;
-      dwarf2_start_subfile (m_cu, *fe, *m_line_header);
-    }
-}
-
-void
-lnp_state_machine::handle_const_add_pc ()
-{
-  CORE_ADDR adjust
-    = (255 - m_line_header->opcode_base) / m_line_header->line_range;
-
-  CORE_ADDR addr_adj
-    = (((m_op_index + adjust)
-	/ m_line_header->maximum_ops_per_instruction)
-       * m_line_header->minimum_instruction_length);
-
-  addr_adj = gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
-  m_address = (unrelocated_addr) ((CORE_ADDR) m_address + addr_adj);
-  m_op_index = ((m_op_index + adjust)
-		% m_line_header->maximum_ops_per_instruction);
-}
-
-/* Return non-zero if we should add LINE to the line number table.
-   LINE is the line to add, LAST_LINE is the last line that was added,
-   LAST_SUBFILE is the subfile for LAST_LINE.
-   LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
-   had a non-zero discriminator.
-
-   We have to be careful in the presence of discriminators.
-   E.g., for this line:
-
-     for (i = 0; i < 100000; i++);
-
-   clang can emit four line number entries for that one line,
-   each with a different discriminator.
-   See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
-
-   However, we want gdb to coalesce all four entries into one.
-   Otherwise the user could stepi into the middle of the line and
-   gdb would get confused about whether the pc really was in the
-   middle of the line.
-
-   Things are further complicated by the fact that two consecutive
-   line number entries for the same line is a heuristic used by gcc
-   to denote the end of the prologue.  So we can't just discard duplicate
-   entries, we have to be selective about it.  The heuristic we use is
-   that we only collapse consecutive entries for the same line if at least
-   one of those entries has a non-zero discriminator.  PR 17276.
-
-   Note: Addresses in the line number state machine can never go backwards
-   within one sequence, thus this coalescing is ok.  */
-
-static int
-dwarf_record_line_p (struct dwarf2_cu *cu,
-		     unsigned int line, unsigned int last_line,
-		     int line_has_non_zero_discriminator,
-		     struct subfile *last_subfile)
-{
-  if (cu->get_builder ()->get_current_subfile () != last_subfile)
-    return 1;
-  if (line != last_line)
-    return 1;
-  /* Same line for the same file that we've seen already.
-     As a last check, for pr 17276, only record the line if the line
-     has never had a non-zero discriminator.  */
-  if (!line_has_non_zero_discriminator)
-    return 1;
-  return 0;
-}
-
-/* Use the CU's builder to record line number LINE beginning at
-   address ADDRESS in the line table of subfile SUBFILE.  */
-
-static void
-dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
-		     unsigned int line, unrelocated_addr address,
-		     linetable_entry_flags flags,
-		     struct dwarf2_cu *cu)
-{
-  unrelocated_addr addr
-    = unrelocated_addr (gdbarch_addr_bits_remove (gdbarch,
-						  (CORE_ADDR) address));
-
-  if (cu != nullptr)
-    {
-      if (dwarf_line_debug)
-	gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
-		    line, lbasename (subfile->name.c_str ()),
-		    paddress (gdbarch, (CORE_ADDR) address));
-
-      cu->get_builder ()->record_line (subfile, line, addr, flags);
-    }
-}
-
-/* Subroutine of dwarf_decode_lines_1 to simplify it.
-   Mark the end of a set of line number records.
-   The arguments are the same as for dwarf_record_line_1.
-   If SUBFILE is NULL the request is ignored.  */
-
-static void
-dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
-		   unrelocated_addr address, struct dwarf2_cu *cu)
-{
-  if (subfile == NULL)
-    return;
-
-  if (dwarf_line_debug)
-    {
-      gdb_printf (gdb_stdlog,
-		  "Finishing current line, file %s, address %s\n",
-		  lbasename (subfile->name.c_str ()),
-		  paddress (gdbarch, (CORE_ADDR) address));
-    }
-
-  dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
-}
-
-void
-lnp_state_machine::record_line (bool end_sequence)
-{
-  if (dwarf_line_debug)
-    {
-      gdb_printf (gdb_stdlog,
-		  "Processing actual line %u: file %u,"
-		  " address %s, is_stmt %u, prologue_end %u,"
-		  " epilogue_begin %u, discrim %u%s\n",
-		  m_line, m_file,
-		  paddress (m_gdbarch, (CORE_ADDR) m_address),
-		  (m_flags & LEF_IS_STMT) != 0,
-		  (m_flags & LEF_PROLOGUE_END) != 0,
-		  (m_flags & LEF_EPILOGUE_BEGIN) != 0,
-		  m_discriminator,
-		  (end_sequence ? "\t(end sequence)" : ""));
-    }
-
-  file_entry *fe = current_file ();
-
-  if (fe == NULL)
-    dwarf2_debug_line_missing_file_complaint ();
-  /* For now we ignore lines not starting on an instruction boundary.
-     But not when processing end_sequence for compatibility with the
-     previous version of the code.  */
-  else if (m_op_index == 0 || end_sequence)
-    {
-      /* When we switch files we insert an end maker in the first file,
-	 switch to the second file and add a new line entry.  The
-	 problem is that the end marker inserted in the first file will
-	 discard any previous line entries at the same address.  If the
-	 line entries in the first file are marked as is-stmt, while
-	 the new line in the second file is non-stmt, then this means
-	 the end marker will discard is-stmt lines so we can have a
-	 non-stmt line.  This means that there are less addresses at
-	 which the user can insert a breakpoint.
-
-	 To improve this we track the last address in m_last_address,
-	 and whether we have seen an is-stmt at this address.  Then
-	 when switching files, if we have seen a stmt at the current
-	 address, and we are switching to create a non-stmt line, then
-	 discard the new line.  */
-      bool file_changed
-	= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
-      bool ignore_this_line
-	= ((file_changed && !end_sequence && m_last_address == m_address
-	    && ((m_flags & LEF_IS_STMT) == 0)
-	    && m_stmt_at_address)
-	   || (!end_sequence && m_line == 0));
-
-      if ((file_changed && !ignore_this_line) || end_sequence)
-	{
-	  dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
-			     m_currently_recording_lines ? m_cu : nullptr);
-	}
-
-      if (!end_sequence && !ignore_this_line)
-	{
-	  linetable_entry_flags lte_flags = m_flags;
-	  if (m_cu->producer_is_codewarrior ())
-	    lte_flags |= LEF_IS_STMT;
-
-	  if (dwarf_record_line_p (m_cu, m_line, m_last_line,
-				   m_line_has_non_zero_discriminator,
-				   m_last_subfile))
-	    {
-	      buildsym_compunit *builder = m_cu->get_builder ();
-	      dwarf_record_line_1 (m_gdbarch,
-				   builder->get_current_subfile (),
-				   m_line, m_address, lte_flags,
-				   m_currently_recording_lines ? m_cu : nullptr);
-
-	      m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
-	      m_last_line = m_line;
-	    }
-	}
-    }
-
-  /* Track whether we have seen any IS_STMT true at m_address in case we
-     have multiple line table entries all at m_address.  */
-  if (m_last_address != m_address)
-    {
-      m_stmt_at_address = false;
-      m_last_address = m_address;
-    }
-  m_stmt_at_address |= (m_flags & LEF_IS_STMT) != 0;
-}
-
-lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
-				      line_header *lh)
-  : m_cu (cu),
-    m_gdbarch (arch),
-    m_line_header (lh),
-    /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as
-       if there was a line entry for it so that the backend has a
-       chance to adjust it and also record it in case it needs it.
-       This is currently used by MIPS code,
-       cf. `mips_adjust_dwarf2_line'.  */
-    m_address ((unrelocated_addr) gdbarch_adjust_dwarf2_line (arch, 0, 0)),
-    m_flags (lh->default_is_stmt ? LEF_IS_STMT : (linetable_entry_flags) 0),
-    m_last_address (m_address)
-{
-}
+/* See dwarf2/read.h.  */
 
 void
-lnp_state_machine::check_line_address (struct dwarf2_cu *cu,
-				       const gdb_byte *line_ptr,
-				       unrelocated_addr unrelocated_lowpc,
-				       unrelocated_addr address)
-{
-  /* Linkers resolve a symbolic relocation referencing a GC'd function to 0,
-     -1 or -2 (-2 is used by certain lld versions, see
-     https://github.com/llvm/llvm-project/commit/e618ccbf431f6730edb6d1467a127c3a52fd57f7).
-     If ADDRESS is 0, ignoring the opcode will err if the text section is
-     located at 0x0.  In this case, additionally check that if
-     ADDRESS < UNRELOCATED_LOWPC.  */
-
-  if ((address == (unrelocated_addr) 0 && address < unrelocated_lowpc)
-      || address == (unrelocated_addr) -1
-      || address == (unrelocated_addr) -2)
-    {
-      /* This line table is for a function which has been
-	 GCd by the linker.  Ignore it.  PR gdb/12528 */
-
-      struct objfile *objfile = cu->per_objfile->objfile;
-      long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
-
-      complaint (_(".debug_line address at offset 0x%lx is 0 [in module %s]"),
-		 line_offset, objfile_name (objfile));
-      m_currently_recording_lines = false;
-      /* Note: m_currently_recording_lines is left as false until we see
-	 DW_LNE_end_sequence.  */
-    }
-}
-
-/* Subroutine of dwarf_decode_lines to simplify it.
-   Process the line number information in LH.  */
-
-static void
-dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
-		      unrelocated_addr lowpc)
-{
-  const gdb_byte *line_ptr, *extended_end;
-  const gdb_byte *line_end;
-  unsigned int bytes_read, extended_len;
-  unsigned char op_code, extended_op;
-  struct objfile *objfile = cu->per_objfile->objfile;
-  bfd *abfd = objfile->obfd.get ();
-  struct gdbarch *gdbarch = objfile->arch ();
-
-  line_ptr = lh->statement_program_start;
-  line_end = lh->statement_program_end;
-
-  /* Read the statement sequences until there's nothing left.  */
-  while (line_ptr < line_end)
-    {
-      /* The DWARF line number program state machine.  Reset the state
-	 machine at the start of each sequence.  */
-      lnp_state_machine state_machine (cu, gdbarch, lh);
-      bool end_sequence = false;
-
-      /* Start a subfile for the current file of the state
-	 machine.  */
-      const file_entry *fe = state_machine.current_file ();
-
-      if (fe != NULL)
-	dwarf2_start_subfile (cu, *fe, *lh);
-
-      /* Decode the table.  */
-      while (line_ptr < line_end && !end_sequence)
-	{
-	  op_code = read_1_byte (abfd, line_ptr);
-	  line_ptr += 1;
-
-	  if (op_code >= lh->opcode_base)
-	    {
-	      /* Special opcode.  */
-	      state_machine.handle_special_opcode (op_code);
-	    }
-	  else switch (op_code)
-	    {
-	    case DW_LNS_extended_op:
-	      extended_len = read_unsigned_leb128 (abfd, line_ptr,
-						   &bytes_read);
-	      line_ptr += bytes_read;
-	      extended_end = line_ptr + extended_len;
-	      extended_op = read_1_byte (abfd, line_ptr);
-	      line_ptr += 1;
-	      if (DW_LNE_lo_user <= extended_op
-		  && extended_op <= DW_LNE_hi_user)
-		{
-		  /* Vendor extension, ignore.  */
-		  line_ptr = extended_end;
-		  break;
-		}
-	      switch (extended_op)
-		{
-		case DW_LNE_end_sequence:
-		  state_machine.handle_end_sequence ();
-		  end_sequence = true;
-		  break;
-		case DW_LNE_set_address:
-		  {
-		    unrelocated_addr address
-		      = cu->header.read_address (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-
-		    state_machine.check_line_address (cu, line_ptr, lowpc,
-						      address);
-		    state_machine.handle_set_address (address);
-		  }
-		  break;
-		case DW_LNE_define_file:
-		  {
-		    const char *cur_file;
-		    unsigned int mod_time, length;
-		    dir_index dindex;
-
-		    cur_file = read_direct_string (abfd, line_ptr,
-						   &bytes_read);
-		    line_ptr += bytes_read;
-		    dindex = (dir_index)
-		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-		    mod_time =
-		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-		    length =
-		      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-		    lh->add_file_name (cur_file, dindex, mod_time, length);
-		  }
-		  break;
-		case DW_LNE_set_discriminator:
-		  {
-		    /* The discriminator is not interesting to the
-		       debugger; just ignore it.  We still need to
-		       check its value though:
-		       if there are consecutive entries for the same
-		       (non-prologue) line we want to coalesce them.
-		       PR 17276.  */
-		    unsigned int discr
-		      = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-
-		    state_machine.handle_set_discriminator (discr);
-		  }
-		  break;
-		default:
-		  complaint (_("mangled .debug_line section"));
-		  return;
-		}
-	      /* Make sure that we parsed the extended op correctly.  If e.g.
-		 we expected a different address size than the producer used,
-		 we may have read the wrong number of bytes.  */
-	      if (line_ptr != extended_end)
-		{
-		  complaint (_("mangled .debug_line section"));
-		  return;
-		}
-	      break;
-	    case DW_LNS_copy:
-	      state_machine.handle_copy ();
-	      break;
-	    case DW_LNS_advance_pc:
-	      {
-		CORE_ADDR adjust
-		  = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		line_ptr += bytes_read;
-
-		state_machine.handle_advance_pc (adjust);
-	      }
-	      break;
-	    case DW_LNS_advance_line:
-	      {
-		int line_delta
-		  = read_signed_leb128 (abfd, line_ptr, &bytes_read);
-		line_ptr += bytes_read;
-
-		state_machine.handle_advance_line (line_delta);
-	      }
-	      break;
-	    case DW_LNS_set_file:
-	      {
-		file_name_index file
-		  = (file_name_index) read_unsigned_leb128 (abfd, line_ptr,
-							    &bytes_read);
-		line_ptr += bytes_read;
-
-		state_machine.handle_set_file (file);
-	      }
-	      break;
-	    case DW_LNS_set_column:
-	      (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-	      line_ptr += bytes_read;
-	      break;
-	    case DW_LNS_negate_stmt:
-	      state_machine.handle_negate_stmt ();
-	      break;
-	    case DW_LNS_set_basic_block:
-	      break;
-	    /* Add to the address register of the state machine the
-	       address increment value corresponding to special opcode
-	       255.  I.e., this value is scaled by the minimum
-	       instruction length since special opcode 255 would have
-	       scaled the increment.  */
-	    case DW_LNS_const_add_pc:
-	      state_machine.handle_const_add_pc ();
-	      break;
-	    case DW_LNS_fixed_advance_pc:
-	      {
-		CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr);
-		line_ptr += 2;
-
-		state_machine.handle_fixed_advance_pc (addr_adj);
-	      }
-	      break;
-	    case DW_LNS_set_prologue_end:
-	      state_machine.handle_set_prologue_end ();
-	      break;
-	    case DW_LNS_set_epilogue_begin:
-	      state_machine.handle_set_epilogue_begin ();
-	      break;
-	    default:
-	      {
-		/* Unknown standard opcode, ignore it.  */
-		int i;
-
-		for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
-		  {
-		    (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-		    line_ptr += bytes_read;
-		  }
-	      }
-	    }
-	}
-
-      if (!end_sequence)
-	dwarf2_debug_line_missing_end_sequence_complaint ();
-
-      /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
-	 in which case we still finish recording the last line).  */
-      state_machine.record_line (true);
-    }
-}
-
-/* Decode the Line Number Program (LNP) for the given line_header
-   structure and CU.  The actual information extracted and the type
-   of structures created from the LNP depends on the value of PST.
-
-   FND holds the CU file name and directory, if known.
-   It is used for relative paths in the line table.
-
-   NOTE: It is important that psymtabs have the same file name (via
-   strcmp) as the corresponding symtab.  Since the directory is not
-   used in the name of the symtab we don't use it in the name of the
-   psymtabs we create.  E.g. expand_line_sal requires this when
-   finding psymtabs to expand.  A good testcase for this is
-   mb-inline.exp.
-
-   LOWPC is the lowest address in CU (or 0 if not known).
-
-   Boolean DECODE_MAPPING specifies we need to fully decode .debug_line
-   for its PC<->lines mapping information.  Otherwise only the filename
-   table is read in.  */
-
-static void
-dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
-		    unrelocated_addr lowpc, int decode_mapping)
-{
-  if (decode_mapping)
-    dwarf_decode_lines_1 (lh, cu, lowpc);
-
-  /* Make sure a symtab is created for every file, even files
-     which contain only variables (i.e. no code with associated
-     line numbers).  */
-  buildsym_compunit *builder = cu->get_builder ();
-  struct compunit_symtab *cust = builder->get_compunit_symtab ();
-
-  for (auto &fe : lh->file_names ())
-    {
-      dwarf2_start_subfile (cu, fe, *lh);
-      subfile *sf = builder->get_current_subfile ();
-
-      if (sf->symtab == nullptr)
-	sf->symtab = allocate_symtab (cust, sf->name.c_str (),
-				      sf->name_for_id.c_str ());
-
-      fe.symtab = sf->symtab;
-    }
-}
-
-/* Start a subfile for DWARF.  FILENAME is the name of the file and
-   DIRNAME the name of the source directory which contains FILENAME
-   or NULL if not known.
-   This routine tries to keep line numbers from identical absolute and
-   relative file names in a common subfile.
-
-   Using the `list' example from the GDB testsuite, which resides in
-   /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
-   of /srcdir/list0.c yields the following debugging information for list0.c:
-
-   DW_AT_name:          /srcdir/list0.c
-   DW_AT_comp_dir:      /compdir
-   files.files[0].name: list0.h
-   files.files[0].dir:  /srcdir
-   files.files[1].name: list0.c
-   files.files[1].dir:  /srcdir
-
-   The line number information for list0.c has to end up in a single
-   subfile, so that `break /srcdir/list0.c:1' works as expected.
-   start_subfile will ensure that this happens provided that we pass the
-   concatenation of files.files[1].dir and files.files[1].name as the
-   subfile's name.  */
-
-static void
 dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
 		      const line_header &lh)
 {
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 74ec4204cadbc38d9d66f8a6a5cac432297a88ff..12c8666a7350246c71d1bbf97119ce6fa1d25a50 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -1351,4 +1351,35 @@ extern file_and_directory &find_file_and_directory (die_info *die,
 extern const dwarf2_section_info &get_section_for_ref
   (const attribute &attr, dwarf2_cu *cu);
 
+/* A convenience function to find the proper .debug_line section for a CU.  */
+
+extern struct dwarf2_section_info *get_debug_line_section
+  (struct dwarf2_cu *cu);
+
+struct file_entry;
+/* Start a subfile for DWARF.  FILENAME is the name of the file and
+   DIRNAME the name of the source directory which contains FILENAME
+   or NULL if not known.
+   This routine tries to keep line numbers from identical absolute and
+   relative file names in a common subfile.
+
+   Using the `list' example from the GDB testsuite, which resides in
+   /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
+   of /srcdir/list0.c yields the following debugging information for list0.c:
+
+   DW_AT_name:          /srcdir/list0.c
+   DW_AT_comp_dir:      /compdir
+   files.files[0].name: list0.h
+   files.files[0].dir:  /srcdir
+   files.files[1].name: list0.c
+   files.files[1].dir:  /srcdir
+
+   The line number information for list0.c has to end up in a single
+   subfile, so that `break /srcdir/list0.c:1' works as expected.
+   start_subfile will ensure that this happens provided that we pass the
+   concatenation of files.files[1].dir and files.files[1].name as the
+   subfile's name.  */
+extern void dwarf2_start_subfile (dwarf2_cu *cu, const file_entry &fe,
+				  const line_header &lh);
+
 #endif /* GDB_DWARF2_READ_H */

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 2/7] Move compute_include_file_name earlier
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
  2025-09-07 19:29 ` [PATCH 1/7] Move lnp_state_machine to new file Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 16:08   ` Simon Marchi
  2025-09-07 19:29 ` [PATCH 3/7] Boolify line-program.c Tom Tromey
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

I noticed that the compute_include_file_name intro comment was
slightly wrong, and while looking at this, I also noticed that it has
a single caller.  This patch hoists it slightly so that a forward
declaration isn't needed.
---
 gdb/dwarf2/read.c | 144 ++++++++++++++++++++++++++----------------------------
 1 file changed, 69 insertions(+), 75 deletions(-)

diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index efff522d9b36f70fb7f37d426ab744bb6d4085b3..30a0141b65d01e6f280a57ffb0350b94aae7ed91 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1037,12 +1037,6 @@ dwarf2_per_cu_deleter::operator() (dwarf2_per_cu *data)
     delete data;
 }
 
-static const char *compute_include_file_name
-     (const struct line_header *lh,
-      const file_entry &fe,
-      const file_and_directory &cu_info,
-      std::string &name_holder);
-
 static struct dwo_unit *lookup_dwo_unit_in_dwp
   (dwarf2_per_bfd *per_bfd, struct dwp_file *dwp_file,
    const char *comp_dir, ULONGEST signature, int is_debug_types);
@@ -1692,6 +1686,75 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
   return result;
 }
 
+/* Subroutine of dw2_get_file_names_reader to simplify it.
+   Return the file name for the given file_entry.
+   CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
+   If space for the result is malloc'd, *NAME_HOLDER will be set.
+   Returns NULL if FILE_INDEX should be ignored, i.e., it is
+   equivalent to CU_INFO.  */
+
+static const char *
+compute_include_file_name (const struct line_header *lh, const file_entry &fe,
+			   const file_and_directory &cu_info,
+			   std::string &name_holder)
+{
+  const char *include_name = fe.name;
+  const char *include_name_to_compare = include_name;
+
+  const char *dir_name = fe.include_dir (lh);
+
+  std::string hold_compare;
+  if (!IS_ABSOLUTE_PATH (include_name)
+      && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
+    {
+      /* Avoid creating a duplicate name for CU_INFO.
+	 We do this by comparing INCLUDE_NAME and CU_INFO.
+	 Before we do the comparison, however, we need to account
+	 for DIR_NAME and COMP_DIR.
+	 First prepend dir_name (if non-NULL).  If we still don't
+	 have an absolute path prepend comp_dir (if non-NULL).
+	 However, the directory we record in the include-file's
+	 psymtab does not contain COMP_DIR (to match the
+	 corresponding symtab(s)).
+
+	 Example:
+
+	 bash$ cd /tmp
+	 bash$ gcc -g ./hello.c
+	 include_name = "hello.c"
+	 dir_name = "."
+	 DW_AT_comp_dir = comp_dir = "/tmp"
+	 DW_AT_name = "./hello.c"
+
+      */
+
+      if (dir_name != NULL)
+	{
+	  name_holder = path_join (dir_name, include_name);
+	  include_name = name_holder.c_str ();
+	  include_name_to_compare = include_name;
+	}
+      if (!IS_ABSOLUTE_PATH (include_name)
+	  && cu_info.get_comp_dir () != nullptr)
+	{
+	  hold_compare = path_join (cu_info.get_comp_dir (), include_name);
+	  include_name_to_compare = hold_compare.c_str ();
+	}
+    }
+
+  std::string copied_name;
+  const char *cu_filename = cu_info.get_name ();
+  if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
+    {
+      copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
+      cu_filename = copied_name.c_str ();
+    }
+
+  if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
+    return nullptr;
+  return include_name;
+}
+
 /* die_reader_func for dw2_get_file_names.  */
 
 static void
@@ -15793,75 +15856,6 @@ dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu,
 				   comp_dir);
 }
 
-/* Subroutine of dwarf_decode_lines to simplify it.
-   Return the file name for the given file_entry.
-   CU_INFO describes the CU's DW_AT_name and DW_AT_comp_dir.
-   If space for the result is malloc'd, *NAME_HOLDER will be set.
-   Returns NULL if FILE_INDEX should be ignored, i.e., it is
-   equivalent to CU_INFO.  */
-
-static const char *
-compute_include_file_name (const struct line_header *lh, const file_entry &fe,
-			   const file_and_directory &cu_info,
-			   std::string &name_holder)
-{
-  const char *include_name = fe.name;
-  const char *include_name_to_compare = include_name;
-
-  const char *dir_name = fe.include_dir (lh);
-
-  std::string hold_compare;
-  if (!IS_ABSOLUTE_PATH (include_name)
-      && (dir_name != nullptr || cu_info.get_comp_dir () != nullptr))
-    {
-      /* Avoid creating a duplicate name for CU_INFO.
-	 We do this by comparing INCLUDE_NAME and CU_INFO.
-	 Before we do the comparison, however, we need to account
-	 for DIR_NAME and COMP_DIR.
-	 First prepend dir_name (if non-NULL).  If we still don't
-	 have an absolute path prepend comp_dir (if non-NULL).
-	 However, the directory we record in the include-file's
-	 psymtab does not contain COMP_DIR (to match the
-	 corresponding symtab(s)).
-
-	 Example:
-
-	 bash$ cd /tmp
-	 bash$ gcc -g ./hello.c
-	 include_name = "hello.c"
-	 dir_name = "."
-	 DW_AT_comp_dir = comp_dir = "/tmp"
-	 DW_AT_name = "./hello.c"
-
-      */
-
-      if (dir_name != NULL)
-	{
-	  name_holder = path_join (dir_name, include_name);
-	  include_name = name_holder.c_str ();
-	  include_name_to_compare = include_name;
-	}
-      if (!IS_ABSOLUTE_PATH (include_name)
-	  && cu_info.get_comp_dir () != nullptr)
-	{
-	  hold_compare = path_join (cu_info.get_comp_dir (), include_name);
-	  include_name_to_compare = hold_compare.c_str ();
-	}
-    }
-
-  std::string copied_name;
-  const char *cu_filename = cu_info.get_name ();
-  if (!IS_ABSOLUTE_PATH (cu_filename) && cu_info.get_comp_dir () != nullptr)
-    {
-      copied_name = path_join (cu_info.get_comp_dir (), cu_filename);
-      cu_filename = copied_name.c_str ();
-    }
-
-  if (FILENAME_CMP (include_name_to_compare, cu_filename) == 0)
-    return nullptr;
-  return include_name;
-}
-
 /* See dwarf2/read.h.  */
 
 void

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 3/7] Boolify line-program.c
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
  2025-09-07 19:29 ` [PATCH 1/7] Move lnp_state_machine to new file Tom Tromey
  2025-09-07 19:29 ` [PATCH 2/7] Move compute_include_file_name earlier Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 17:07   ` Simon Marchi
  2025-09-07 19:29 ` [PATCH 4/7] Change dwarf_record_line_p to be a method Tom Tromey
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes some code in line-program.c to use bool rather than int.
---
 gdb/dwarf2/line-program.c | 12 ++++++------
 gdb/dwarf2/line-program.h |  2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index 72bdd1f5a748ce228114105597b1e5a162254f69..5292d3d5e86722bc6d60b049740982c06550ef76 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -291,22 +291,22 @@ lnp_state_machine::handle_const_add_pc ()
    Note: Addresses in the line number state machine can never go backwards
    within one sequence, thus this coalescing is ok.  */
 
-static int
+static bool
 dwarf_record_line_p (struct dwarf2_cu *cu,
 		     unsigned int line, unsigned int last_line,
 		     int line_has_non_zero_discriminator,
 		     struct subfile *last_subfile)
 {
   if (cu->get_builder ()->get_current_subfile () != last_subfile)
-    return 1;
+    return true;
   if (line != last_line)
-    return 1;
+    return true;
   /* Same line for the same file that we've seen already.
      As a last check, for pr 17276, only record the line if the line
      has never had a non-zero discriminator.  */
   if (!line_has_non_zero_discriminator)
-    return 1;
-  return 0;
+    return true;
+  return false;
 }
 
 /* Use the CU's builder to record line number LINE beginning at
@@ -706,7 +706,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
 
 void
 dwarf_decode_lines (struct line_header *lh, struct dwarf2_cu *cu,
-		    unrelocated_addr lowpc, int decode_mapping)
+		    unrelocated_addr lowpc, bool decode_mapping)
 {
   if (decode_mapping)
     dwarf_decode_lines_1 (lh, cu, lowpc);
diff --git a/gdb/dwarf2/line-program.h b/gdb/dwarf2/line-program.h
index c84403253e635225d7c27d49a91dd1581fa0fa2e..824f18f9613c55a714d1889666ad25045ba1dba8 100644
--- a/gdb/dwarf2/line-program.h
+++ b/gdb/dwarf2/line-program.h
@@ -42,6 +42,6 @@
 
 extern void dwarf_decode_lines (struct line_header *lh,
 				struct dwarf2_cu *cu,
-				unrelocated_addr lowpc, int decode_mapping);
+				unrelocated_addr lowpc, bool decode_mapping);
 
 #endif /* GDB_DWARF2_LINE_PROGRAM_H */

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 4/7] Change dwarf_record_line_p to be a method
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
                   ` (2 preceding siblings ...)
  2025-09-07 19:29 ` [PATCH 3/7] Boolify line-program.c Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-07 19:29 ` [PATCH 5/7] Add m_builder member to lnp_state_machine Tom Tromey
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf_record_line_p to be a method of lnp_state_machine.
This simplifies it, as it can refer to members of the object.
---
 gdb/dwarf2/line-program.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index 5292d3d5e86722bc6d60b049740982c06550ef76..e1a9f31bed409884808dd690ada942a58e66dd91 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -150,6 +150,8 @@ class lnp_state_machine
       m_line_has_non_zero_discriminator = m_discriminator != 0;
   }
 
+  bool record_line_p ();
+
   struct dwarf2_cu *m_cu;
 
   gdbarch *m_gdbarch;
@@ -291,20 +293,17 @@ lnp_state_machine::handle_const_add_pc ()
    Note: Addresses in the line number state machine can never go backwards
    within one sequence, thus this coalescing is ok.  */
 
-static bool
-dwarf_record_line_p (struct dwarf2_cu *cu,
-		     unsigned int line, unsigned int last_line,
-		     int line_has_non_zero_discriminator,
-		     struct subfile *last_subfile)
+bool
+lnp_state_machine::record_line_p ()
 {
-  if (cu->get_builder ()->get_current_subfile () != last_subfile)
+  if (m_cu->get_builder ()->get_current_subfile () != m_last_subfile)
     return true;
-  if (line != last_line)
+  if (m_line != m_last_line)
     return true;
   /* Same line for the same file that we've seen already.
      As a last check, for pr 17276, only record the line if the line
      has never had a non-zero discriminator.  */
-  if (!line_has_non_zero_discriminator)
+  if (!m_line_has_non_zero_discriminator)
     return true;
   return false;
 }
@@ -418,9 +417,7 @@ lnp_state_machine::record_line (bool end_sequence)
 	  if (m_cu->producer_is_codewarrior ())
 	    lte_flags |= LEF_IS_STMT;
 
-	  if (dwarf_record_line_p (m_cu, m_line, m_last_line,
-				   m_line_has_non_zero_discriminator,
-				   m_last_subfile))
+	  if (record_line_p ())
 	    {
 	      buildsym_compunit *builder = m_cu->get_builder ();
 	      dwarf_record_line_1 (m_gdbarch,

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 5/7] Add m_builder member to lnp_state_machine
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
                   ` (3 preceding siblings ...)
  2025-09-07 19:29 ` [PATCH 4/7] Change dwarf_record_line_p to be a method Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 17:12   ` Simon Marchi
  2025-09-07 19:29 ` [PATCH 6/7] Change dwarf_finish_line to be a method Tom Tromey
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

I noticed that several spots in lnp_state_machine fetch the CU's
builder.  Since this can't change over the lifetime of the object, it
seemed nicer to simply cache it.
---
 gdb/dwarf2/line-program.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index e1a9f31bed409884808dd690ada942a58e66dd91..732f6fa13357dfa66c2ba493b186cabbcb08285a 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -154,6 +154,9 @@ class lnp_state_machine
 
   struct dwarf2_cu *m_cu;
 
+  /* The builder associated with the CU.  */
+  buildsym_compunit *m_builder;
+
   gdbarch *m_gdbarch;
 
   /* The line number header.  */
@@ -296,7 +299,7 @@ lnp_state_machine::handle_const_add_pc ()
 bool
 lnp_state_machine::record_line_p ()
 {
-  if (m_cu->get_builder ()->get_current_subfile () != m_last_subfile)
+  if (m_builder->get_current_subfile () != m_last_subfile)
     return true;
   if (m_line != m_last_line)
     return true;
@@ -398,7 +401,7 @@ lnp_state_machine::record_line (bool end_sequence)
 	 address, and we are switching to create a non-stmt line, then
 	 discard the new line.  */
       bool file_changed
-	= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
+	= m_last_subfile != m_builder->get_current_subfile ();
       bool ignore_this_line
 	= ((file_changed && !end_sequence && m_last_address == m_address
 	    && ((m_flags & LEF_IS_STMT) == 0)
@@ -419,13 +422,12 @@ lnp_state_machine::record_line (bool end_sequence)
 
 	  if (record_line_p ())
 	    {
-	      buildsym_compunit *builder = m_cu->get_builder ();
 	      dwarf_record_line_1 (m_gdbarch,
-				   builder->get_current_subfile (),
+				   m_builder->get_current_subfile (),
 				   m_line, m_address, lte_flags,
 				   m_currently_recording_lines ? m_cu : nullptr);
 
-	      m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
+	      m_last_subfile = m_builder->get_current_subfile ();
 	      m_last_line = m_line;
 	    }
 	}
@@ -444,6 +446,7 @@ lnp_state_machine::record_line (bool end_sequence)
 lnp_state_machine::lnp_state_machine (struct dwarf2_cu *cu, gdbarch *arch,
 				      line_header *lh)
   : m_cu (cu),
+    m_builder (cu->get_builder ()),
     m_gdbarch (arch),
     m_line_header (lh),
     /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 6/7] Change dwarf_finish_line to be a method
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
                   ` (4 preceding siblings ...)
  2025-09-07 19:29 ` [PATCH 5/7] Add m_builder member to lnp_state_machine Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 17:14   ` Simon Marchi
  2025-09-07 19:29 ` [PATCH 7/7] Change dwarf_record_line_1 " Tom Tromey
  2025-09-08 17:18 ` [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Simon Marchi
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf_finish_line to be a method of lnp_state_machine,
simplifying it a bit.
---
 gdb/dwarf2/line-program.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index 732f6fa13357dfa66c2ba493b186cabbcb08285a..b6007e368344216af3e09d2651d9483b7d2940e6 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -151,6 +151,7 @@ class lnp_state_machine
   }
 
   bool record_line_p ();
+  void finish_line ();
 
   struct dwarf2_cu *m_cu;
 
@@ -337,25 +338,24 @@ dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
 
 /* Subroutine of dwarf_decode_lines_1 to simplify it.
    Mark the end of a set of line number records.
-   The arguments are the same as for dwarf_record_line_1.
    If SUBFILE is NULL the request is ignored.  */
 
-static void
-dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
-		   unrelocated_addr address, struct dwarf2_cu *cu)
+void
+lnp_state_machine::finish_line ()
 {
-  if (subfile == NULL)
+  if (m_last_subfile == nullptr)
     return;
 
   if (dwarf_line_debug)
     {
       gdb_printf (gdb_stdlog,
 		  "Finishing current line, file %s, address %s\n",
-		  lbasename (subfile->name.c_str ()),
-		  paddress (gdbarch, (CORE_ADDR) address));
+		  lbasename (m_last_subfile->name.c_str ()),
+		  paddress (m_gdbarch, (CORE_ADDR) m_address));
     }
 
-  dwarf_record_line_1 (gdbarch, subfile, 0, address, LEF_IS_STMT, cu);
+  dwarf_record_line_1 (m_gdbarch, m_last_subfile, 0, m_address, LEF_IS_STMT,
+		       m_currently_recording_lines ? m_cu : nullptr);
 }
 
 void
@@ -409,10 +409,7 @@ lnp_state_machine::record_line (bool end_sequence)
 	   || (!end_sequence && m_line == 0));
 
       if ((file_changed && !ignore_this_line) || end_sequence)
-	{
-	  dwarf_finish_line (m_gdbarch, m_last_subfile, m_address,
-			     m_currently_recording_lines ? m_cu : nullptr);
-	}
+	finish_line ();
 
       if (!end_sequence && !ignore_this_line)
 	{

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 7/7] Change dwarf_record_line_1 to be a method
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
                   ` (5 preceding siblings ...)
  2025-09-07 19:29 ` [PATCH 6/7] Change dwarf_finish_line to be a method Tom Tromey
@ 2025-09-07 19:29 ` Tom Tromey
  2025-09-08 17:17   ` Simon Marchi
  2025-09-08 17:18 ` [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Simon Marchi
  7 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-07 19:29 UTC (permalink / raw)
  To: gdb-patches; +Cc: Tom Tromey

This changes dwarf_record_line_1 to be a method of lnp_state_machine,
simplifying it a bit.
---
 gdb/dwarf2/line-program.c | 34 ++++++++++++++--------------------
 1 file changed, 14 insertions(+), 20 deletions(-)

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index b6007e368344216af3e09d2651d9483b7d2940e6..48ae4befd5409f11d73a01cbf565b735442ce886 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -152,6 +152,7 @@ class lnp_state_machine
 
   bool record_line_p ();
   void finish_line ();
+  void record_line_1 (unsigned int line, linetable_entry_flags flags);
 
   struct dwarf2_cu *m_cu;
 
@@ -315,24 +316,22 @@ lnp_state_machine::record_line_p ()
 /* Use the CU's builder to record line number LINE beginning at
    address ADDRESS in the line table of subfile SUBFILE.  */
 
-static void
-dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
-		     unsigned int line, unrelocated_addr address,
-		     linetable_entry_flags flags,
-		     struct dwarf2_cu *cu)
+void
+lnp_state_machine::record_line_1 (unsigned int line,
+				  linetable_entry_flags flags)
 {
-  unrelocated_addr addr
-    = unrelocated_addr (gdbarch_addr_bits_remove (gdbarch,
-						  (CORE_ADDR) address));
-
-  if (cu != nullptr)
+  if (m_currently_recording_lines)
     {
+      unrelocated_addr addr
+	= unrelocated_addr (gdbarch_addr_bits_remove (m_gdbarch,
+						      (CORE_ADDR) m_address));
+
       if (dwarf_line_debug)
 	gdb_printf (gdb_stdlog, "Recording line %u, file %s, address %s\n",
-		    line, lbasename (subfile->name.c_str ()),
-		    paddress (gdbarch, (CORE_ADDR) address));
+		    m_line, lbasename (m_last_subfile->name.c_str ()),
+		    paddress (m_gdbarch, (CORE_ADDR) addr));
 
-      cu->get_builder ()->record_line (subfile, line, addr, flags);
+      m_builder->record_line (m_last_subfile, line, addr, flags);
     }
 }
 
@@ -354,8 +353,7 @@ lnp_state_machine::finish_line ()
 		  paddress (m_gdbarch, (CORE_ADDR) m_address));
     }
 
-  dwarf_record_line_1 (m_gdbarch, m_last_subfile, 0, m_address, LEF_IS_STMT,
-		       m_currently_recording_lines ? m_cu : nullptr);
+  record_line_1 (0, LEF_IS_STMT);
 }
 
 void
@@ -419,12 +417,8 @@ lnp_state_machine::record_line (bool end_sequence)
 
 	  if (record_line_p ())
 	    {
-	      dwarf_record_line_1 (m_gdbarch,
-				   m_builder->get_current_subfile (),
-				   m_line, m_address, lte_flags,
-				   m_currently_recording_lines ? m_cu : nullptr);
-
 	      m_last_subfile = m_builder->get_current_subfile ();
+	      record_line_1 (m_line, lte_flags);
 	      m_last_line = m_line;
 	    }
 	}

-- 
2.49.0


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-07 19:29 ` [PATCH 1/7] Move lnp_state_machine to new file Tom Tromey
@ 2025-09-08 16:04   ` Simon Marchi
  2025-09-09  0:51     ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 16:04 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> This patch moves lnp_state_machine and some supporting code to a new
> file, dwarf2/line-program.c.  The main benefit of this is shrinking
> dwarf2/read.c a bit.
> ---
>  gdb/Makefile.in           |   1 +
>  gdb/dwarf2/line-program.c | 731 ++++++++++++++++++++++++++++++++++++++++++++
>  gdb/dwarf2/line-program.h |  47 +++
>  gdb/dwarf2/read.c         | 757 +---------------------------------------------
>  gdb/dwarf2/read.h         |  31 ++
>  5 files changed, 814 insertions(+), 753 deletions(-)
> 
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index 7654fb1aa04465e570b2e06f9a223b95448b0ca2..d7f8b95cae736255d4d26bc6c85cb8e22675c9f1 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1910,6 +1910,7 @@ DWARF2_SRCS = \
>  	dwarf2/index-write.c \
>  	dwarf2/leb.c \
>  	dwarf2/line-header.c \
> +	dwarf2/line-program.c \
>  	dwarf2/loc.c \
>  	dwarf2/macro.c \
>  	dwarf2/parent-map.c \

I think we're supposed to add header files to the HFILES_NO_SRCDIR
variable (although I'm sure it's missing some).

> diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
> index 74ec4204cadbc38d9d66f8a6a5cac432297a88ff..12c8666a7350246c71d1bbf97119ce6fa1d25a50 100644
> --- a/gdb/dwarf2/read.h
> +++ b/gdb/dwarf2/read.h
> @@ -1351,4 +1351,35 @@ extern file_and_directory &find_file_and_directory (die_info *die,
>  extern const dwarf2_section_info &get_section_for_ref
>    (const attribute &attr, dwarf2_cu *cu);
>  
> +/* A convenience function to find the proper .debug_line section for a CU.  */
> +
> +extern struct dwarf2_section_info *get_debug_line_section
> +  (struct dwarf2_cu *cu);
> +
> +struct file_entry;

I would put this at the top with the other forward decls.

Otherwise, looks very nice.  That's a good chunk of code out of read.c.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/7] Move compute_include_file_name earlier
  2025-09-07 19:29 ` [PATCH 2/7] Move compute_include_file_name earlier Tom Tromey
@ 2025-09-08 16:08   ` Simon Marchi
  2025-09-09  0:46     ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 16:08 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> I noticed that the compute_include_file_name intro comment was
> slightly wrong, and while looking at this, I also noticed that it has
> a single caller.  This patch hoists it slightly so that a forward
> declaration isn't needed.

Looks fine to me, but it isn't clear from the above if you intended to
fix something in the comment (I don't see any changes).

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-07 19:29 ` [PATCH 3/7] Boolify line-program.c Tom Tromey
@ 2025-09-08 17:07   ` Simon Marchi
  2025-09-09  0:48     ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 17:07 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> This changes some code in line-program.c to use bool rather than int.

At the same time, I think you could fix the divergent intro comments
(one in the header, one in the source file).

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 5/7] Add m_builder member to lnp_state_machine
  2025-09-07 19:29 ` [PATCH 5/7] Add m_builder member to lnp_state_machine Tom Tromey
@ 2025-09-08 17:12   ` Simon Marchi
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 17:12 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> @@ -398,7 +401,7 @@ lnp_state_machine::record_line (bool end_sequence)
>  	 address, and we are switching to create a non-stmt line, then
>  	 discard the new line.  */
>        bool file_changed
> -	= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
> +	= m_last_subfile != m_builder->get_current_subfile ();

This now fits on a single line.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 6/7] Change dwarf_finish_line to be a method
  2025-09-07 19:29 ` [PATCH 6/7] Change dwarf_finish_line to be a method Tom Tromey
@ 2025-09-08 17:14   ` Simon Marchi
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 17:14 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> This changes dwarf_finish_line to be a method of lnp_state_machine,
> simplifying it a bit.
> ---
>  gdb/dwarf2/line-program.c | 21 +++++++++------------
>  1 file changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
> index 732f6fa13357dfa66c2ba493b186cabbcb08285a..b6007e368344216af3e09d2651d9483b7d2940e6 100644
> --- a/gdb/dwarf2/line-program.c
> +++ b/gdb/dwarf2/line-program.c
> @@ -151,6 +151,7 @@ class lnp_state_machine
>    }
>  
>    bool record_line_p ();
> +  void finish_line ();
>  
>    struct dwarf2_cu *m_cu;
>  
> @@ -337,25 +338,24 @@ dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
>  
>  /* Subroutine of dwarf_decode_lines_1 to simplify it.
>     Mark the end of a set of line number records.
> -   The arguments are the same as for dwarf_record_line_1.
>     If SUBFILE is NULL the request is ignored.  */
>  
> -static void
> -dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
> -		   unrelocated_addr address, struct dwarf2_cu *cu)
> +void
> +lnp_state_machine::finish_line ()

The intro comment would need to be updated, since it refers to SUBFILE.
The previous two patches contained some instances of that too I think,
and I forgot to mention them.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 7/7] Change dwarf_record_line_1 to be a method
  2025-09-07 19:29 ` [PATCH 7/7] Change dwarf_record_line_1 " Tom Tromey
@ 2025-09-08 17:17   ` Simon Marchi
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 17:17 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> This changes dwarf_record_line_1 to be a method of lnp_state_machine,
> simplifying it a bit.
> ---
>  gdb/dwarf2/line-program.c | 34 ++++++++++++++--------------------
>  1 file changed, 14 insertions(+), 20 deletions(-)
> 
> diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
> index b6007e368344216af3e09d2651d9483b7d2940e6..48ae4befd5409f11d73a01cbf565b735442ce886 100644
> --- a/gdb/dwarf2/line-program.c
> +++ b/gdb/dwarf2/line-program.c
> @@ -152,6 +152,7 @@ class lnp_state_machine
>  
>    bool record_line_p ();
>    void finish_line ();
> +  void record_line_1 (unsigned int line, linetable_entry_flags flags);
>  
>    struct dwarf2_cu *m_cu;
>  
> @@ -315,24 +316,22 @@ lnp_state_machine::record_line_p ()
>  /* Use the CU's builder to record line number LINE beginning at
>     address ADDRESS in the line table of subfile SUBFILE.  */
>  
> -static void
> -dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
> -		     unsigned int line, unrelocated_addr address,
> -		     linetable_entry_flags flags,
> -		     struct dwarf2_cu *cu)
> +void
> +lnp_state_machine::record_line_1 (unsigned int line,
> +				  linetable_entry_flags flags)

The comment refers to the removed ADDRESS and SUBFILE parameters.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine
  2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
                   ` (6 preceding siblings ...)
  2025-09-07 19:29 ` [PATCH 7/7] Change dwarf_record_line_1 " Tom Tromey
@ 2025-09-08 17:18 ` Simon Marchi
  2025-09-09  0:54   ` Tom Tromey
  7 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-08 17:18 UTC (permalink / raw)
  To: Tom Tromey, gdb-patches

On 9/7/25 3:29 PM, Tom Tromey wrote:
> This started with a patch to shrink dwarf2/read.c a bit, by moving
> lnp_state_machine to its own file.  Then I proceeded to clean up that
> code a tiny bit.
> 
> Regression tested on x86-64 Fedora 40.
> 
> Signed-off-by: Tom Tromey <tom@tromey.com>
> ---
> Tom Tromey (7):
>       Move lnp_state_machine to new file
>       Move compute_include_file_name earlier
>       Boolify line-program.c
>       Change dwarf_record_line_p to be a method
>       Add m_builder member to lnp_state_machine
>       Change dwarf_finish_line to be a method
>       Change dwarf_record_line_1 to be a method
> 
>  gdb/Makefile.in           |   1 +
>  gdb/dwarf2/line-program.c | 722 +++++++++++++++++++++++++++++++++++++
>  gdb/dwarf2/line-program.h |  47 +++
>  gdb/dwarf2/read.c         | 901 ++++------------------------------------------
>  gdb/dwarf2/read.h         |  31 ++
>  5 files changed, 874 insertions(+), 828 deletions(-)
> ---
> base-commit: 46ada32fc979550ad4f46792b74c182bb7232aeb
> change-id: 20250907-breakpoint-cu-expand-852f7e832aaa
> 
> Best regards,
> -- 
> Tom Tromey <tom@tromey.com>
> 

Thanks for doing this.  I think some comments would need updating, but
other than that it LGTM.  I don't think these changes warrant a new
version.

Approved-By: Simon Marchi <simon.marchi@efficios.com>

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 2/7] Move compute_include_file_name earlier
  2025-09-08 16:08   ` Simon Marchi
@ 2025-09-09  0:46     ` Tom Tromey
  0 siblings, 0 replies; 26+ messages in thread
From: Tom Tromey @ 2025-09-09  0:46 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

Simon> On 9/7/25 3:29 PM, Tom Tromey wrote:
>> I noticed that the compute_include_file_name intro comment was
>> slightly wrong, and while looking at this, I also noticed that it has
>> a single caller.  This patch hoists it slightly so that a forward
>> declaration isn't needed.

Simon> Looks fine to me, but it isn't clear from the above if you intended to
Simon> fix something in the comment (I don't see any changes).

The change is just the name of the function it helps:

-/* Subroutine of dwarf_decode_lines to simplify it.
+/* Subroutine of dw2_get_file_names_reader to simplify it.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-08 17:07   ` Simon Marchi
@ 2025-09-09  0:48     ` Tom Tromey
  2025-09-09  0:50       ` Simon Marchi
  0 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-09  0:48 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

Simon> On 9/7/25 3:29 PM, Tom Tromey wrote:
>> This changes some code in line-program.c to use bool rather than int.

Simon> At the same time, I think you could fix the divergent intro comments
Simon> (one in the header, one in the source file).

I fixed the appended but the comment in the header looks correct to me?
Anyway if you can point out what is wrong I will fix it.

Tom

diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index 48ae4befd54..27356bd3e14 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -268,7 +268,7 @@ lnp_state_machine::handle_const_add_pc ()
 		% m_line_header->maximum_ops_per_instruction);
 }
 
-/* Return non-zero if we should add LINE to the line number table.
+/* Return true if we should add LINE to the line number table.
    LINE is the line to add, LAST_LINE is the last line that was added,
    LAST_SUBFILE is the subfile for LAST_LINE.
    LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-09  0:48     ` Tom Tromey
@ 2025-09-09  0:50       ` Simon Marchi
  2025-09-09  1:11         ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-09  0:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches



On 2025-09-08 20:48, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:
> 
> Simon> On 9/7/25 3:29 PM, Tom Tromey wrote:
>>> This changes some code in line-program.c to use bool rather than int.
> 
> Simon> At the same time, I think you could fix the divergent intro comments
> Simon> (one in the header, one in the source file).
> 
> I fixed the appended but the comment in the header looks correct to me?
> Anyway if you can point out what is wrong I will fix it.
> 
> Tom

The actual intro comment should be in the header, with the usual

  /* See ... */

in the source file.  It looks like the comments diverged a bit, when
that happens I try to pick the best of both.  For instance, it looks
like the comment in the header doesn't have the "Return non-zero if..."
part.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-08 16:04   ` Simon Marchi
@ 2025-09-09  0:51     ` Tom Tromey
  2025-09-09  0:52       ` Simon Marchi
  0 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-09  0:51 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

Simon> I think we're supposed to add header files to the HFILES_NO_SRCDIR
Simon> variable (although I'm sure it's missing some).

We are and I wonder if anybody even uses "make tags", because it is
currently broken.  So perhaps we could remove this code.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-09  0:51     ` Tom Tromey
@ 2025-09-09  0:52       ` Simon Marchi
  2025-09-09  2:33         ` Eli Zaretskii
  0 siblings, 1 reply; 26+ messages in thread
From: Simon Marchi @ 2025-09-09  0:52 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches



On 2025-09-08 20:51, Tom Tromey wrote:
> Simon> I think we're supposed to add header files to the HFILES_NO_SRCDIR
> Simon> variable (although I'm sure it's missing some).
> 
> We are and I wonder if anybody even uses "make tags", because it is
> currently broken.  So perhaps we could remove this code.
> 
> Tom

Lol, I almost asked "does anybody uses tags these days?" but decided not
too because it did sound a bit too aggressive.  But if indeed nobody
uses it, I am always happy to delete unnecessary stuff.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine
  2025-09-08 17:18 ` [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Simon Marchi
@ 2025-09-09  0:54   ` Tom Tromey
  0 siblings, 0 replies; 26+ messages in thread
From: Tom Tromey @ 2025-09-09  0:54 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

Simon> Thanks for doing this.  I think some comments would need updating, but
Simon> other than that it LGTM.  I don't think these changes warrant a new
Simon> version.

Thanks.  I made the changes & rebuilt & did some re-testing.
I'll push it shortly.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-09  0:50       ` Simon Marchi
@ 2025-09-09  1:11         ` Tom Tromey
  2025-09-09 23:55           ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-09  1:11 UTC (permalink / raw)
  To: Simon Marchi; +Cc: Tom Tromey, gdb-patches

>>>>> "Simon" == Simon Marchi <simark@simark.ca> writes:

>> I fixed the appended but the comment in the header looks correct to me?
>> Anyway if you can point out what is wrong I will fix it.

Simon> The actual intro comment should be in the header, with the usual

Simon>   /* See ... */

Simon> in the source file.  It looks like the comments diverged a bit, when
Simon> that happens I try to pick the best of both.  For instance, it looks
Simon> like the comment in the header doesn't have the "Return non-zero if..."
Simon> part.

I pushed this already but I will look at it again & fix it tomorrow.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-09  0:52       ` Simon Marchi
@ 2025-09-09  2:33         ` Eli Zaretskii
  2025-09-09 23:25           ` Tom Tromey
  0 siblings, 1 reply; 26+ messages in thread
From: Eli Zaretskii @ 2025-09-09  2:33 UTC (permalink / raw)
  To: Simon Marchi; +Cc: tom, gdb-patches

> Date: Mon, 8 Sep 2025 20:52:50 -0400
> Cc: gdb-patches@sourceware.org
> From: Simon Marchi <simark@simark.ca>
> 
> 
> 
> On 2025-09-08 20:51, Tom Tromey wrote:
> > Simon> I think we're supposed to add header files to the HFILES_NO_SRCDIR
> > Simon> variable (although I'm sure it's missing some).
> > 
> > We are and I wonder if anybody even uses "make tags", because it is
> > currently broken.  So perhaps we could remove this code.
> > 
> > Tom
> 
> Lol, I almost asked "does anybody uses tags these days?" but decided not
> too because it did sound a bit too aggressive.  But if indeed nobody
> uses it, I am always happy to delete unnecessary stuff.

Please don't delete it.  I use it all the time, and always test it
when I build a pretest (which will happen soon with GDB 17).

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 1/7] Move lnp_state_machine to new file
  2025-09-09  2:33         ` Eli Zaretskii
@ 2025-09-09 23:25           ` Tom Tromey
  0 siblings, 0 replies; 26+ messages in thread
From: Tom Tromey @ 2025-09-09 23:25 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: Simon Marchi, tom, gdb-patches

Eli> Please don't delete it.

No problem.

Eli> I use it all the time, and always test it
Eli> when I build a pretest (which will happen soon with GDB 17).

I tried updating the list but the sorting advice at the top of
Makefile.in is weird -- I think it'd be better if we replaced it with
plain old "sort".

Anyway I'll send a patch but not one that uses the documented order.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-09  1:11         ` Tom Tromey
@ 2025-09-09 23:55           ` Tom Tromey
  2025-09-10  1:51             ` Simon Marchi
  0 siblings, 1 reply; 26+ messages in thread
From: Tom Tromey @ 2025-09-09 23:55 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Simon Marchi, gdb-patches

Simon> The actual intro comment should be in the header, with the usual

Simon> /* See ... */

Simon> in the source file.  It looks like the comments diverged a bit, when
Simon> that happens I try to pick the best of both.  For instance, it looks
Simon> like the comment in the header doesn't have the "Return non-zero if..."
Simon> part.

Tom> I pushed this already but I will look at it again & fix it tomorrow.

I looked at this again, and for the function in question (which I think
is dwarf_decode_lines), the doc comment is in the header
(line-program.h) and the .c file has a "see..." comment.  So I don't see
an issue.

If it's something else let me know.

Tom

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 3/7] Boolify line-program.c
  2025-09-09 23:55           ` Tom Tromey
@ 2025-09-10  1:51             ` Simon Marchi
  0 siblings, 0 replies; 26+ messages in thread
From: Simon Marchi @ 2025-09-10  1:51 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches



On 2025-09-09 19:55, Tom Tromey wrote:
> Simon> The actual intro comment should be in the header, with the usual
> 
> Simon> /* See ... */
> 
> Simon> in the source file.  It looks like the comments diverged a bit, when
> Simon> that happens I try to pick the best of both.  For instance, it looks
> Simon> like the comment in the header doesn't have the "Return non-zero if..."
> Simon> part.
> 
> Tom> I pushed this already but I will look at it again & fix it tomorrow.
> 
> I looked at this again, and for the function in question (which I think
> is dwarf_decode_lines), the doc comment is in the header
> (line-program.h) and the .c file has a "see..." comment.  So I don't see
> an issue.
> 
> If it's something else let me know.
> 
> Tom

Ah, sorry, I did confuse dwarf_record_line_p with dwarf_decode_lines, in
line-program.c.  Nevermind.

Simon

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2025-09-10  1:52 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-07 19:29 [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Tom Tromey
2025-09-07 19:29 ` [PATCH 1/7] Move lnp_state_machine to new file Tom Tromey
2025-09-08 16:04   ` Simon Marchi
2025-09-09  0:51     ` Tom Tromey
2025-09-09  0:52       ` Simon Marchi
2025-09-09  2:33         ` Eli Zaretskii
2025-09-09 23:25           ` Tom Tromey
2025-09-07 19:29 ` [PATCH 2/7] Move compute_include_file_name earlier Tom Tromey
2025-09-08 16:08   ` Simon Marchi
2025-09-09  0:46     ` Tom Tromey
2025-09-07 19:29 ` [PATCH 3/7] Boolify line-program.c Tom Tromey
2025-09-08 17:07   ` Simon Marchi
2025-09-09  0:48     ` Tom Tromey
2025-09-09  0:50       ` Simon Marchi
2025-09-09  1:11         ` Tom Tromey
2025-09-09 23:55           ` Tom Tromey
2025-09-10  1:51             ` Simon Marchi
2025-09-07 19:29 ` [PATCH 4/7] Change dwarf_record_line_p to be a method Tom Tromey
2025-09-07 19:29 ` [PATCH 5/7] Add m_builder member to lnp_state_machine Tom Tromey
2025-09-08 17:12   ` Simon Marchi
2025-09-07 19:29 ` [PATCH 6/7] Change dwarf_finish_line to be a method Tom Tromey
2025-09-08 17:14   ` Simon Marchi
2025-09-07 19:29 ` [PATCH 7/7] Change dwarf_record_line_1 " Tom Tromey
2025-09-08 17:17   ` Simon Marchi
2025-09-08 17:18 ` [PATCH 0/7] Shrink dwarf2/read.c and clean up lnp_state_machine Simon Marchi
2025-09-09  0:54   ` Tom Tromey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox