2012-03-01 Pedro Alves <palves@redhat.com>
authorPedro Alves <palves@redhat.com>
Thu, 1 Mar 2012 20:49:02 +0000 (20:49 +0000)
committerPedro Alves <palves@redhat.com>
Thu, 1 Mar 2012 20:49:02 +0000 (20:49 +0000)
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/ChangeLog
gdb/frame.c
gdb/frame.h
gdb/i387-tdep.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.trace/unavailable.exp

index 1230229507d52ff06cd9948420043a4c24e688a6..f20d58bf9a53441d3ff5c3d10b782d3f3c1b09f5 100644 (file)
@@ -1,3 +1,14 @@
+2012-03-01  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/13767
+
+       * 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.
+
 2012-03-01  Keith Seitz  <keiths@redhat.com>
 
        * linespec.c (decode_line_2): Sort the list of methods
index 5e51ca6f388ea64473aacd6b086ee986fea0c80f..e012f2dbe752d54da5eca88d67886aa2506278a1 100644 (file)
@@ -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)
index 67dddbdb747b332ef1d9a01cfa943e5d248648d5..101db3b3eee4283b11a0d750c471c249584561db 100644 (file)
@@ -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
index 450b8f21a1c2f2f606ae8b8687cef5d571c36cef..27f3c5b6050c2685663c8ab9564084056279bef2 100644 (file)
@@ -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>"));
 }
 \f
 
index d41a2c80ba64ce715e0c4f77b14de39d515805aa..63825431e92816a36b84c474ae863702e4b06463 100644 (file)
@@ -1,3 +1,10 @@
+2012-03-01  Pedro Alves  <palves@redhat.com>
+
+       PR gdb/13767
+
+       * gdb.trace/unavailable.exp (gdb_unavailable_floats): New.
+       (gdb_collect_globals_test): Call it.
+
 2012-03-01  Keith Seitz  <keiths@redhat.com>
 
        * gdb.cp/method2.exp: Output of overload menu is now
index be79b8675d6bcd2361755002484408cccc5fd9aa..bc5f8931bf785bc1b2df35ae73a7da9d95cc45f0 100644 (file)
@@ -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"