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]

[PATCH] PR gdb/13767: "info float" and unavailable float registers (traceframes)


I'm checking this in.  It makes "info float" on x86* handle
unavailable float registers gracefully.

Before:

  (gdb) info float
    R7: Empty   Register 31 is not available

After:

  (gdb) info float

  Status Word:         <unavailable>
  Control Word:        <unavailable>
  Tag Word:            <unavailable>
  Instruction Pointer: <unavailable>:<unavailable>
  Operand Pointer:     <unavailable>:<unavailable>
  Opcode:              <unavailable>

I've accounted for the possibility of having only some of the state
available (instead of a all or nothing), for when we do get to support
collecting floats.

Tested on x86_64 Fedora 16.  Also ran the unavailable.ext test with -m32.

2012-03-01  Pedro Alves  <palves@redhat.com>

	PR gdb/13767

	gdb/
	* frame.c (read_frame_register_unsigned): New.
	* frame.h (read_frame_register_unsigned): Declare.
	* i387-tdep.c (print_i387_status_word): New parameter `status_p'.
	Handle it.
	(print_i387_control_word): New parameter `control_p'.  Handle it.
	(i387_print_float_info): Handle unavailable float registers.

	gdb/testsuite/
	* gdb.trace/unavailable.exp (gdb_unavailable_floats): New.
	(gdb_collect_globals_test): Call it.
---
 gdb/testsuite/gdb.trace/unavailable.exp |   34 +++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/gdb/frame.c b/gdb/frame.c
index 5e51ca6..e012f2d 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -1031,6 +1031,26 @@ get_frame_register_unsigned (struct frame_info *frame, int regnum)
   return frame_unwind_register_unsigned (frame->next, regnum);
 }
 
+int
+read_frame_register_unsigned (struct frame_info *frame, int regnum,
+			      ULONGEST *val)
+{
+  struct value *regval = get_frame_register_value (frame, regnum);
+
+  if (!value_optimized_out (regval)
+      && value_entirely_available (regval))
+    {
+      struct gdbarch *gdbarch = get_frame_arch (frame);
+      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      int size = register_size (gdbarch, VALUE_REGNUM (regval));
+
+      *val = extract_unsigned_integer (value_contents (regval), size, byte_order);
+      return 1;
+    }
+
+  return 0;
+}
+
 void
 put_frame_register (struct frame_info *frame, int regnum,
 		    const gdb_byte *buf)
diff --git a/gdb/frame.h b/gdb/frame.h
index 67dddbd..101db3b 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -500,6 +500,13 @@ extern ULONGEST frame_unwind_register_unsigned (struct frame_info *frame,
 extern ULONGEST get_frame_register_unsigned (struct frame_info *frame,
 					     int regnum);
 
+/* Read a a register from this, or unwind a register from the next
+   frame.  Note that the read_frame methods are wrappers to
+   get_frame_register_value, that do not throw if the result is
+   optimized out or unavailable.  */
+
+extern int read_frame_register_unsigned (struct frame_info *frame,
+					 int regnum, ULONGEST *val);
 
 /* Get the value of the register that belongs to this FRAME.  This
    function is a wrapper to the call sequence ``frame_register_unwind
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 450b8f2..27f3c5b 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -113,13 +113,21 @@ print_i387_ext (struct gdbarch *gdbarch,
     fputs_filtered (" Unsupported", file);
 }
 
-/* Print the status word STATUS.  */
+/* Print the status word STATUS.  If STATUS_P is false, then STATUS
+   was unavailable.  */
 
 static void
-print_i387_status_word (unsigned int status, struct ui_file *file)
+print_i387_status_word (int status_p,
+			unsigned int status, struct ui_file *file)
 {
-  fprintf_filtered (file, "Status Word:         %s",
-		    hex_string_custom (status, 4));
+  fprintf_filtered (file, "Status Word:         ");
+  if (!status_p)
+    {
+      fprintf_filtered (file, "%s\n", _("<unavailable>"));
+      return;
+    }
+
+  fprintf_filtered (file, "%s", hex_string_custom (status, 4));
   fputs_filtered ("  ", file);
   fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : "  ");
   fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : "  ");
@@ -143,13 +151,21 @@ print_i387_status_word (unsigned int status, struct ui_file *file)
 		    "                       TOP: %d\n", ((status >> 11) & 7));
 }
 
-/* Print the control word CONTROL.  */
+/* Print the control word CONTROL.  If CONTROL_P is false, then
+   CONTROL was unavailable.  */
 
 static void
-print_i387_control_word (unsigned int control, struct ui_file *file)
+print_i387_control_word (int control_p,
+			 unsigned int control, struct ui_file *file)
 {
-  fprintf_filtered (file, "Control Word:        %s",
-		    hex_string_custom (control, 4));
+  fprintf_filtered (file, "Control Word:        ");
+  if (!control_p)
+    {
+      fprintf_filtered (file, "%s\n", _("<unavailable>"));
+      return;
+    }
+
+  fprintf_filtered (file, "%s", hex_string_custom (control, 4));
   fputs_filtered ("  ", file);
   fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : "  ");
   fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : "  ");
@@ -205,81 +221,119 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
   ULONGEST fctrl;
+  int fctrl_p;
   ULONGEST fstat;
+  int fstat_p;
   ULONGEST ftag;
+  int ftag_p;
   ULONGEST fiseg;
+  int fiseg_p;
   ULONGEST fioff;
+  int fioff_p;
   ULONGEST foseg;
+  int foseg_p;
   ULONGEST fooff;
+  int fooff_p;
   ULONGEST fop;
+  int fop_p;
   int fpreg;
+  int fpreg_p;
   int top;
+  int top_p;
 
   gdb_assert (gdbarch == get_frame_arch (frame));
 
-  fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM (tdep));
-  fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM (tdep));
-  ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM (tdep));
-  fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM (tdep));
-  fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM (tdep));
-  foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM (tdep));
-  fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM (tdep));
-  fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM (tdep));
+  fctrl_p = read_frame_register_unsigned (frame,
+					  I387_FCTRL_REGNUM (tdep), &fctrl);
+  fstat_p = read_frame_register_unsigned (frame,
+					  I387_FSTAT_REGNUM (tdep), &fstat);
+  ftag_p = read_frame_register_unsigned (frame,
+					 I387_FTAG_REGNUM (tdep), &ftag);
+  fiseg_p = read_frame_register_unsigned (frame,
+					  I387_FISEG_REGNUM (tdep), &fiseg);
+  fioff_p = read_frame_register_unsigned (frame,
+					  I387_FIOFF_REGNUM (tdep), &fioff);
+  foseg_p = read_frame_register_unsigned (frame,
+					  I387_FOSEG_REGNUM (tdep), &foseg);
+  fooff_p = read_frame_register_unsigned (frame,
+					  I387_FOOFF_REGNUM (tdep), &fooff);
+  fop_p = read_frame_register_unsigned (frame,
+					I387_FOP_REGNUM (tdep), &fop);
+
+  if (fstat_p)
+    {
+      top = ((fstat >> 11) & 7);
 
-  top = ((fstat >> 11) & 7);
+      for (fpreg = 7; fpreg >= 0; fpreg--)
+	{
+	  struct value *regval;
+	  int regnum;
+	  int i;
+	  int tag = -1;
 
-  for (fpreg = 7; fpreg >= 0; fpreg--)
-    {
-      gdb_byte raw[I386_MAX_REGISTER_SIZE];
-      int tag = (ftag >> (fpreg * 2)) & 3;
-      int i;
+	  fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
 
-      fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : "  ", fpreg);
+	  if (ftag_p)
+	    {
+	      tag = (ftag >> (fpreg * 2)) & 3;
 
-      switch (tag)
-	{
-	case 0:
-	  fputs_filtered ("Valid   ", file);
-	  break;
-	case 1:
-	  fputs_filtered ("Zero    ", file);
-	  break;
-	case 2:
-	  fputs_filtered ("Special ", file);
-	  break;
-	case 3:
-	  fputs_filtered ("Empty   ", file);
-	  break;
-	}
+	      switch (tag)
+		{
+		case 0:
+		  fputs_filtered ("Valid   ", file);
+		  break;
+		case 1:
+		  fputs_filtered ("Zero    ", file);
+		  break;
+		case 2:
+		  fputs_filtered ("Special ", file);
+		  break;
+		case 3:
+		  fputs_filtered ("Empty   ", file);
+		  break;
+		}
+	    }
+	  else
+	    fputs_filtered ("Unknown ", file);
 
-      get_frame_register (frame,
-			  (fpreg + 8 - top) % 8 + I387_ST0_REGNUM (tdep),
-			  raw);
+	  regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM (tdep);
+	  regval = get_frame_register_value (frame, regnum);
 
-      fputs_filtered ("0x", file);
-      for (i = 9; i >= 0; i--)
-	fprintf_filtered (file, "%02x", raw[i]);
+	  if (value_entirely_available (regval))
+	    {
+	      const char *raw = value_contents (regval);
+
+	      fputs_filtered ("0x", file);
+	      for (i = 9; i >= 0; i--)
+		fprintf_filtered (file, "%02x", raw[i]);
 
-      if (tag != 3)
-	print_i387_ext (gdbarch, raw, file);
+	      if (tag != -1 && tag != 3)
+		print_i387_ext (gdbarch, raw, file);
+	    }
+	  else
+	    fprintf_filtered (file, "%s", _("<unavailable>"));
 
-      fputs_filtered ("\n", file);
+	  fputs_filtered ("\n", file);
+	}
     }
 
   fputs_filtered ("\n", file);
-
-  print_i387_status_word (fstat, file);
-  print_i387_control_word (fctrl, file);
+  print_i387_status_word (fstat_p, fstat, file);
+  print_i387_control_word (fctrl_p, fctrl, file);
   fprintf_filtered (file, "Tag Word:            %s\n",
-		    hex_string_custom (ftag, 4));
+		    ftag_p ? hex_string_custom (ftag, 4) : _("<unavailable>"));
   fprintf_filtered (file, "Instruction Pointer: %s:",
-		    hex_string_custom (fiseg, 2));
-  fprintf_filtered (file, "%s\n", hex_string_custom (fioff, 8));
+		    fiseg_p ? hex_string_custom (fiseg, 2) : _("<unavailable>"));
+  fprintf_filtered (file, "%s\n",
+		    fioff_p ? hex_string_custom (fioff, 8) : _("<unavailable>"));
   fprintf_filtered (file, "Operand Pointer:     %s:",
-		    hex_string_custom (foseg, 2));
-  fprintf_filtered (file, "%s\n", hex_string_custom (fooff, 8));
+		    foseg_p ? hex_string_custom (foseg, 2) : _("<unavailable>"));
+  fprintf_filtered (file, "%s\n",
+		    fooff_p ? hex_string_custom (fooff, 8) : _("<unavailable>"));
   fprintf_filtered (file, "Opcode:              %s\n",
-		    hex_string_custom (fop ? (fop | 0xd800) : 0, 4));
+		    fop_p
+		    ? (hex_string_custom (fop ? (fop | 0xd800) : 0, 4))
+		    : _("<unavailable>"));
 }
 
 
diff --git a/gdb/testsuite/gdb.trace/unavailable.exp b/gdb/testsuite/gdb.trace/unavailable.exp
index be79b86..bc5f893 100644
--- a/gdb/testsuite/gdb.trace/unavailable.exp
+++ b/gdb/testsuite/gdb.trace/unavailable.exp
@@ -305,6 +305,39 @@ proc gdb_unavailable_registers_test { } { with_test_prefix "unavailable register
     gdb_test "tfind none" "#0  end .*" "cease trace debugging"
 }}
 
+proc gdb_unavailable_floats { } {
+    global gdb_prompt
+
+    with_test_prefix "unavailable floats" {
+	prepare_for_trace_test
+
+	# We'll simply re-use the globals_test_function for this test
+	gdb_test "trace globals_test_func" \
+	    "Tracepoint \[0-9\]+ at .*" \
+	    "set tracepoint"
+
+	# Collect nothing.
+
+	# Begin the test.
+	run_trace_experiment globals_test_func
+
+	# Necessarily target specific.
+	if {[istarget "x86_64-*-*"] || [istarget i?86-*]} {
+	    send_gdb "info float\n"
+	    gdb_expect_list "info float" ".*$gdb_prompt $" {
+		"Status Word:         <unavailable>"
+		"Control Word:        <unavailable>"
+		"Tag Word:            <unavailable>"
+		"Instruction Pointer: <unavailable>:<unavailable>"
+		"Operand Pointer:     <unavailable>:<unavailable>"
+		"Opcode:              <unavailable>"
+	    }
+	}
+
+	gdb_test "tfind none" "#0  end .*" "cease trace debugging"
+    }
+}
+
 proc gdb_collect_globals_test { } { with_test_prefix "collect globals" {
     global ws
     global cr
@@ -547,6 +580,7 @@ proc gdb_collect_globals_test { } { with_test_prefix "collect globals" {
 proc gdb_trace_collection_test {} {
     gdb_collect_globals_test
     gdb_unavailable_registers_test
+    gdb_unavailable_floats
 
     gdb_collect_args_test
     gdb_collect_locals_test local_test_func "auto locals"


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