diff options
author | Pedro Alves <palves@redhat.com> | 2012-03-01 20:49:02 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2012-03-01 20:49:02 +0000 |
commit | ad5f7d6ef7055f46c1734b9862bd156c355a8b3d (patch) | |
tree | fb20ff6ac3ace8b4d6d5c8e9b79bb49e1c415cb7 | |
parent | d3dc44a619a1f52ace35f3cccb16b6096e13b5da (diff) | |
download | gdb-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/ChangeLog | 11 | ||||
-rw-r--r-- | gdb/frame.c | 20 | ||||
-rw-r--r-- | gdb/frame.h | 7 | ||||
-rw-r--r-- | gdb/i387-tdep.c | 166 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.trace/unavailable.exp | 34 |
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" |