This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[pushed] Split value_fetch_lazy


From: Simon Marchi <simon.marchi@ericsson.com>

While reading value_fetch_lazy, I thought it would be good to split it
in small functions (especially the part that handles lval_register).

gdb/ChangeLog:

	* value.c (value_fetch_lazy_bitfield): New.
	(value_fetch_lazy_memory): New.
	(value_fetch_lazy_register): New.
	(value_fetch_lazy): Factor out to smaller functions.
---
 gdb/ChangeLog |   7 ++
 gdb/value.c   | 303 +++++++++++++++++++++++++++-----------------------
 2 files changed, 169 insertions(+), 141 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f1eed4e72991..9895d2fcc3dc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,10 @@
+2018-06-02  Simon Marchi  <simon.marchi@ericsson.com>
+
+	* value.c (value_fetch_lazy_bitfield): New.
+	(value_fetch_lazy_memory): New.
+	(value_fetch_lazy_register): New.
+	(value_fetch_lazy): Factor out to smaller functions.
+
 2018-06-01  Tom Tromey  <tom@tromey.com>
 
 	* cp-name-parser.y (backslashable, represented): Now const.
diff --git a/gdb/value.c b/gdb/value.c
index 6bb6b8eb61eb..146ce8e94db3 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3714,6 +3714,165 @@ value_initialized (const struct value *val)
   return val->initialized;
 }
 
+/* Helper for value_fetch_lazy when the value is a bitfield.  */
+
+static void
+value_fetch_lazy_bitfield (struct value *val)
+{
+  gdb_assert (value_bitsize (val) != 0);
+
+  /* To read a lazy bitfield, read the entire enclosing value.  This
+     prevents reading the same block of (possibly volatile) memory once
+     per bitfield.  It would be even better to read only the containing
+     word, but we have no way to record that just specific bits of a
+     value have been fetched.  */
+  struct type *type = check_typedef (value_type (val));
+  struct value *parent = value_parent (val);
+
+  if (value_lazy (parent))
+    value_fetch_lazy (parent);
+
+  unpack_value_bitfield (val, value_bitpos (val), value_bitsize (val),
+			 value_contents_for_printing (parent),
+			 value_offset (val), parent);
+}
+
+/* Helper for value_fetch_lazy when the value is in memory.  */
+
+static void
+value_fetch_lazy_memory (struct value *val)
+{
+  gdb_assert (VALUE_LVAL (val) == lval_memory);
+
+  CORE_ADDR addr = value_address (val);
+  struct type *type = check_typedef (value_enclosing_type (val));
+
+  if (TYPE_LENGTH (type))
+      read_value_memory (val, 0, value_stack (val),
+			 addr, value_contents_all_raw (val),
+			 type_length_units (type));
+}
+
+/* Helper for value_fetch_lazy when the value is in a register.  */
+
+static void
+value_fetch_lazy_register (struct value *val)
+{
+  struct frame_info *next_frame;
+  int regnum;
+  struct type *type = check_typedef (value_type (val));
+  struct value *new_val = val, *mark = value_mark ();
+
+  /* Offsets are not supported here; lazy register values must
+     refer to the entire register.  */
+  gdb_assert (value_offset (val) == 0);
+
+  while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
+    {
+      struct frame_id next_frame_id = VALUE_NEXT_FRAME_ID (new_val);
+
+      next_frame = frame_find_by_id (next_frame_id);
+      regnum = VALUE_REGNUM (new_val);
+
+      gdb_assert (next_frame != NULL);
+
+      /* Convertible register routines are used for multi-register
+	 values and for interpretation in different types
+	 (e.g. float or int from a double register).  Lazy
+	 register values should have the register's natural type,
+	 so they do not apply.  */
+      gdb_assert (!gdbarch_convert_register_p (get_frame_arch (next_frame),
+					       regnum, type));
+
+      /* FRAME was obtained, above, via VALUE_NEXT_FRAME_ID.
+	 Since a "->next" operation was performed when setting
+	 this field, we do not need to perform a "next" operation
+	 again when unwinding the register.  That's why
+	 frame_unwind_register_value() is called here instead of
+	 get_frame_register_value().  */
+      new_val = frame_unwind_register_value (next_frame, regnum);
+
+      /* If we get another lazy lval_register value, it means the
+	 register is found by reading it from NEXT_FRAME's next frame.
+	 frame_unwind_register_value should never return a value with
+	 the frame id pointing to NEXT_FRAME.  If it does, it means we
+	 either have two consecutive frames with the same frame id
+	 in the frame chain, or some code is trying to unwind
+	 behind get_prev_frame's back (e.g., a frame unwind
+	 sniffer trying to unwind), bypassing its validations.  In
+	 any case, it should always be an internal error to end up
+	 in this situation.  */
+      if (VALUE_LVAL (new_val) == lval_register
+	  && value_lazy (new_val)
+	  && frame_id_eq (VALUE_NEXT_FRAME_ID (new_val), next_frame_id))
+	internal_error (__FILE__, __LINE__,
+			_("infinite loop while fetching a register"));
+    }
+
+  /* If it's still lazy (for instance, a saved register on the
+     stack), fetch it.  */
+  if (value_lazy (new_val))
+    value_fetch_lazy (new_val);
+
+  /* Copy the contents and the unavailability/optimized-out
+     meta-data from NEW_VAL to VAL.  */
+  set_value_lazy (val, 0);
+  value_contents_copy (val, value_embedded_offset (val),
+		       new_val, value_embedded_offset (new_val),
+		       type_length_units (type));
+
+  if (frame_debug)
+    {
+      struct gdbarch *gdbarch;
+      struct frame_info *frame;
+      /* VALUE_FRAME_ID is used here, instead of VALUE_NEXT_FRAME_ID,
+	 so that the frame level will be shown correctly.  */
+      frame = frame_find_by_id (VALUE_FRAME_ID (val));
+      regnum = VALUE_REGNUM (val);
+      gdbarch = get_frame_arch (frame);
+
+      fprintf_unfiltered (gdb_stdlog,
+			  "{ value_fetch_lazy "
+			  "(frame=%d,regnum=%d(%s),...) ",
+			  frame_relative_level (frame), regnum,
+			  user_reg_map_regnum_to_name (gdbarch, regnum));
+
+      fprintf_unfiltered (gdb_stdlog, "->");
+      if (value_optimized_out (new_val))
+	{
+	  fprintf_unfiltered (gdb_stdlog, " ");
+	  val_print_optimized_out (new_val, gdb_stdlog);
+	}
+      else
+	{
+	  int i;
+	  const gdb_byte *buf = value_contents (new_val);
+
+	  if (VALUE_LVAL (new_val) == lval_register)
+	    fprintf_unfiltered (gdb_stdlog, " register=%d",
+				VALUE_REGNUM (new_val));
+	  else if (VALUE_LVAL (new_val) == lval_memory)
+	    fprintf_unfiltered (gdb_stdlog, " address=%s",
+				paddress (gdbarch,
+					  value_address (new_val)));
+	  else
+	    fprintf_unfiltered (gdb_stdlog, " computed");
+
+	  fprintf_unfiltered (gdb_stdlog, " bytes=");
+	  fprintf_unfiltered (gdb_stdlog, "[");
+	  for (i = 0; i < register_size (gdbarch, regnum); i++)
+	    fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
+	  fprintf_unfiltered (gdb_stdlog, "]");
+	}
+
+      fprintf_unfiltered (gdb_stdlog, " }\n");
+    }
+
+  /* Dispose of the intermediate values.  This prevents
+     watchpoints from trying to watch the saved frame pointer.  */
+  value_free_to_mark (mark);
+}
+
 /* Load the actual content of a lazy value.  Fetch the data from the
    user's process and clear the lazy flag to indicate that the data in
    the buffer is valid.
@@ -3733,149 +3892,11 @@ value_fetch_lazy (struct value *val)
   gdb_assert (val->optimized_out.empty ());
   gdb_assert (val->unavailable.empty ());
   if (value_bitsize (val))
-    {
-      /* To read a lazy bitfield, read the entire enclosing value.  This
-	 prevents reading the same block of (possibly volatile) memory once
-         per bitfield.  It would be even better to read only the containing
-         word, but we have no way to record that just specific bits of a
-         value have been fetched.  */
-      struct type *type = check_typedef (value_type (val));
-      struct value *parent = value_parent (val);
-
-      if (value_lazy (parent))
-	value_fetch_lazy (parent);
-
-      unpack_value_bitfield (val,
-			     value_bitpos (val), value_bitsize (val),
-			     value_contents_for_printing (parent),
-			     value_offset (val), parent);
-    }
+    value_fetch_lazy_bitfield (val);
   else if (VALUE_LVAL (val) == lval_memory)
-    {
-      CORE_ADDR addr = value_address (val);
-      struct type *type = check_typedef (value_enclosing_type (val));
-
-      if (TYPE_LENGTH (type))
-	read_value_memory (val, 0, value_stack (val),
-			   addr, value_contents_all_raw (val),
-			   type_length_units (type));
-    }
+    value_fetch_lazy_memory (val);
   else if (VALUE_LVAL (val) == lval_register)
-    {
-      struct frame_info *next_frame;
-      int regnum;
-      struct type *type = check_typedef (value_type (val));
-      struct value *new_val = val, *mark = value_mark ();
-
-      /* Offsets are not supported here; lazy register values must
-	 refer to the entire register.  */
-      gdb_assert (value_offset (val) == 0);
-
-      while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
-	{
-	  struct frame_id next_frame_id = VALUE_NEXT_FRAME_ID (new_val);
-
-	  next_frame = frame_find_by_id (next_frame_id);
-	  regnum = VALUE_REGNUM (new_val);
-
-	  gdb_assert (next_frame != NULL);
-
-	  /* Convertible register routines are used for multi-register
-	     values and for interpretation in different types
-	     (e.g. float or int from a double register).  Lazy
-	     register values should have the register's natural type,
-	     so they do not apply.  */
-	  gdb_assert (!gdbarch_convert_register_p (get_frame_arch (next_frame),
-						   regnum, type));
-
-	  /* FRAME was obtained, above, via VALUE_NEXT_FRAME_ID. 
-	     Since a "->next" operation was performed when setting
-	     this field, we do not need to perform a "next" operation
-	     again when unwinding the register.  That's why
-	     frame_unwind_register_value() is called here instead of
-	     get_frame_register_value().  */
-	  new_val = frame_unwind_register_value (next_frame, regnum);
-
-	  /* If we get another lazy lval_register value, it means the
-	     register is found by reading it from NEXT_FRAME's next frame.
-	     frame_unwind_register_value should never return a value with
-	     the frame id pointing to NEXT_FRAME.  If it does, it means we
-	     either have two consecutive frames with the same frame id
-	     in the frame chain, or some code is trying to unwind
-	     behind get_prev_frame's back (e.g., a frame unwind
-	     sniffer trying to unwind), bypassing its validations.  In
-	     any case, it should always be an internal error to end up
-	     in this situation.  */
-	  if (VALUE_LVAL (new_val) == lval_register
-	      && value_lazy (new_val)
-	      && frame_id_eq (VALUE_NEXT_FRAME_ID (new_val), next_frame_id))
-	    internal_error (__FILE__, __LINE__,
-			    _("infinite loop while fetching a register"));
-	}
-
-      /* If it's still lazy (for instance, a saved register on the
-	 stack), fetch it.  */
-      if (value_lazy (new_val))
-	value_fetch_lazy (new_val);
-
-      /* Copy the contents and the unavailability/optimized-out
-	 meta-data from NEW_VAL to VAL.  */
-      set_value_lazy (val, 0);
-      value_contents_copy (val, value_embedded_offset (val),
-			   new_val, value_embedded_offset (new_val),
-			   type_length_units (type));
-
-      if (frame_debug)
-	{
-	  struct gdbarch *gdbarch;
-	  struct frame_info *frame;
-	  /* VALUE_FRAME_ID is used here, instead of VALUE_NEXT_FRAME_ID,
-	     so that the frame level will be shown correctly.  */
-	  frame = frame_find_by_id (VALUE_FRAME_ID (val));
-	  regnum = VALUE_REGNUM (val);
-	  gdbarch = get_frame_arch (frame);
-
-	  fprintf_unfiltered (gdb_stdlog,
-			      "{ value_fetch_lazy "
-			      "(frame=%d,regnum=%d(%s),...) ",
-			      frame_relative_level (frame), regnum,
-			      user_reg_map_regnum_to_name (gdbarch, regnum));
-
-	  fprintf_unfiltered (gdb_stdlog, "->");
-	  if (value_optimized_out (new_val))
-	    {
-	      fprintf_unfiltered (gdb_stdlog, " ");
-	      val_print_optimized_out (new_val, gdb_stdlog);
-	    }
-	  else
-	    {
-	      int i;
-	      const gdb_byte *buf = value_contents (new_val);
-
-	      if (VALUE_LVAL (new_val) == lval_register)
-		fprintf_unfiltered (gdb_stdlog, " register=%d",
-				    VALUE_REGNUM (new_val));
-	      else if (VALUE_LVAL (new_val) == lval_memory)
-		fprintf_unfiltered (gdb_stdlog, " address=%s",
-				    paddress (gdbarch,
-					      value_address (new_val)));
-	      else
-		fprintf_unfiltered (gdb_stdlog, " computed");
-
-	      fprintf_unfiltered (gdb_stdlog, " bytes=");
-	      fprintf_unfiltered (gdb_stdlog, "[");
-	      for (i = 0; i < register_size (gdbarch, regnum); i++)
-		fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
-	      fprintf_unfiltered (gdb_stdlog, "]");
-	    }
-
-	  fprintf_unfiltered (gdb_stdlog, " }\n");
-	}
-
-      /* Dispose of the intermediate values.  This prevents
-	 watchpoints from trying to watch the saved frame pointer.  */
-      value_free_to_mark (mark);
-    }
+    value_fetch_lazy_register (val);
   else if (VALUE_LVAL (val) == lval_computed
 	   && value_computed_funcs (val)->read != NULL)
     value_computed_funcs (val)->read (val);
-- 
2.17.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]