aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2012-03-01 20:49:02 +0000
committerPedro Alves <palves@redhat.com>2012-03-01 20:49:02 +0000
commitad5f7d6ef7055f46c1734b9862bd156c355a8b3d (patch)
treefb20ff6ac3ace8b4d6d5c8e9b79bb49e1c415cb7
parentd3dc44a619a1f52ace35f3cccb16b6096e13b5da (diff)
downloadgdb-ad5f7d6ef7055f46c1734b9862bd156c355a8b3d.zip
gdb-ad5f7d6ef7055f46c1734b9862bd156c355a8b3d.tar.gz
gdb-ad5f7d6ef7055f46c1734b9862bd156c355a8b3d.tar.bz2
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.
-rw-r--r--gdb/ChangeLog11
-rw-r--r--gdb/frame.c20
-rw-r--r--gdb/frame.h7
-rw-r--r--gdb/i387-tdep.c166
-rw-r--r--gdb/testsuite/ChangeLog7
-rw-r--r--gdb/testsuite/gdb.trace/unavailable.exp34
6 files changed, 189 insertions, 56 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1230229..f20d58b 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
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/ChangeLog b/gdb/testsuite/ChangeLog
index d41a2c8..6382543 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -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
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"