diff options
-rw-r--r-- | gdb/ChangeLog | 20 | ||||
-rw-r--r-- | gdb/frame.c | 108 | ||||
-rw-r--r-- | gdb/frame.h | 8 | ||||
-rw-r--r-- | gdb/stack.c | 27 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.S | 508 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.c | 36 | ||||
-rw-r--r-- | gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.exp | 58 | ||||
-rw-r--r-- | gdb/valprint.c | 8 | ||||
-rw-r--r-- | gdb/valprint.h | 3 |
10 files changed, 723 insertions, 59 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9111314..4748392 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2013-12-06 Pedro Alves <palves@redhat.com> + + * frame.c (enum cached_copy_status): New enum. + (struct frame_info) <prev_pc.p>: Change type to enum + cached_copy_status. + (fprint_frame): Handle not saved and unavailable prev_pc values. + (frame_unwind_pc_if_available): Delete and merge contents into ... + (frame_unwind_pc): ... here. Handle OPTIMIZED_OUT_ERROR. Adjust + to use enum cached_copy_status. + (frame_unwind_caller_pc_if_available): Delete. + (create_new_frame): Adjust. + * frame.h (frame_unwind_caller_pc_if_available): Delete + declaration. + * stack.c (frame_info): Use frame_unwind_caller_pc instead of + frame_unwind_caller_pc_if_available, and handle + NOT_AVAILABLE_ERROR and OPTIMIZED_OUT_ERROR errors. + * valprint.c (val_print_optimized_out): Use val_print_not_saved. + (val_print_not_saved): New function. + * valprint.h (val_print_not_saved): Declare. + 2013-12-06 Andrew Burgess <aburgess@broadcom.com> Pedro Alves <palves@redhat.com> diff --git a/gdb/frame.c b/gdb/frame.c index 0ba1d4d..6a8b5ae 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -50,6 +50,23 @@ static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame); static const char *frame_stop_reason_symbol_string (enum unwind_stop_reason reason); +/* Status of some values cached in the frame_info object. */ + +enum cached_copy_status +{ + /* Value is unknown. */ + CC_UNKNOWN, + + /* We have a value. */ + CC_VALUE, + + /* Value was not saved. */ + CC_NOT_SAVED, + + /* Value is unavailable. */ + CC_UNAVAILABLE +}; + /* We keep a cache of stack frames, each of which is a "struct frame_info". The innermost one gets allocated (in wait_for_inferior) each time the inferior stops; current_frame @@ -96,7 +113,7 @@ struct frame_info /* Cached copy of the previous frame's resume address. */ struct { - int p; + enum cached_copy_status status; CORE_ADDR value; } prev_pc; @@ -366,10 +383,15 @@ fprint_frame (struct ui_file *file, struct frame_info *fi) fprintf_unfiltered (file, "<unknown>"); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "pc="); - if (fi->next != NULL && fi->next->prev_pc.p) - fprintf_unfiltered (file, "%s", hex_string (fi->next->prev_pc.value)); - else + if (fi->next == NULL || fi->next->prev_pc.status == CC_UNKNOWN) fprintf_unfiltered (file, "<unknown>"); + else if (fi->next->prev_pc.status == CC_VALUE) + fprintf_unfiltered (file, "%s", + hex_string (fi->next->prev_pc.value)); + else if (fi->next->prev_pc.status == CC_NOT_SAVED) + val_print_not_saved (file); + else if (fi->next->prev_pc.status == CC_UNAVAILABLE) + val_print_unavailable (file); fprintf_unfiltered (file, ","); fprintf_unfiltered (file, "id="); if (fi->this_id.p) @@ -707,10 +729,10 @@ frame_find_by_id (struct frame_id id) return NULL; } -static int -frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) +static CORE_ADDR +frame_unwind_pc (struct frame_info *this_frame) { - if (!this_frame->prev_pc.p) + if (this_frame->prev_pc.status == CC_UNKNOWN) { if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame))) { @@ -740,24 +762,35 @@ frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); } - if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR) + if (ex.reason < 0) { - this_frame->prev_pc.p = -1; - - if (frame_debug) - fprintf_unfiltered (gdb_stdlog, - "{ frame_unwind_pc (this_frame=%d)" - " -> <unavailable> }\n", - this_frame->level); - } - else if (ex.reason < 0) - { - throw_exception (ex); + if (ex.error == NOT_AVAILABLE_ERROR) + { + this_frame->prev_pc.status = CC_UNAVAILABLE; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> <unavailable> }\n", + this_frame->level); + } + else if (ex.error == OPTIMIZED_OUT_ERROR) + { + this_frame->prev_pc.status = CC_NOT_SAVED; + + if (frame_debug) + fprintf_unfiltered (gdb_stdlog, + "{ frame_unwind_pc (this_frame=%d)" + " -> <not saved> }\n", + this_frame->level); + } + else + throw_exception (ex); } else { this_frame->prev_pc.value = pc; - this_frame->prev_pc.p = 1; + this_frame->prev_pc.status = CC_VALUE; if (frame_debug) fprintf_unfiltered (gdb_stdlog, "{ frame_unwind_pc (this_frame=%d) " @@ -769,27 +802,17 @@ frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc) else internal_error (__FILE__, __LINE__, _("No unwind_pc method")); } - if (this_frame->prev_pc.p < 0) - { - *pc = -1; - return 0; - } - else - { - *pc = this_frame->prev_pc.value; - return 1; - } -} -static CORE_ADDR -frame_unwind_pc (struct frame_info *this_frame) -{ - CORE_ADDR pc; - - if (!frame_unwind_pc_if_available (this_frame, &pc)) + if (this_frame->prev_pc.status == CC_VALUE) + return this_frame->prev_pc.value; + else if (this_frame->prev_pc.status == CC_UNAVAILABLE) throw_error (NOT_AVAILABLE_ERROR, _("PC not available")); + else if (this_frame->prev_pc.status == CC_NOT_SAVED) + throw_error (OPTIMIZED_OUT_ERROR, _("PC not saved")); else - return pc; + internal_error (__FILE__, __LINE__, + "unexpected prev_pc status: %d", + (int) this_frame->prev_pc.status); } CORE_ADDR @@ -799,13 +822,6 @@ frame_unwind_caller_pc (struct frame_info *this_frame) } int -frame_unwind_caller_pc_if_available (struct frame_info *this_frame, - CORE_ADDR *pc) -{ - return frame_unwind_pc_if_available (skip_artificial_frames (this_frame), pc); -} - -int get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc) { struct frame_info *next_frame = this_frame->next; @@ -1572,7 +1588,7 @@ create_new_frame (CORE_ADDR addr, CORE_ADDR pc) very likely to read this, and the corresponding unwinder is entitled to rely that the PC doesn't magically change. */ fi->next->prev_pc.value = pc; - fi->next->prev_pc.p = 1; + fi->next->prev_pc.status = CC_VALUE; /* We currently assume that frame chain's can't cross spaces. */ fi->pspace = fi->next->pspace; diff --git a/gdb/frame.h b/gdb/frame.h index a5e1629..f8d5bc1 100644 --- a/gdb/frame.h +++ b/gdb/frame.h @@ -548,14 +548,6 @@ extern void put_frame_register_bytes (struct frame_info *frame, int regnum, extern CORE_ADDR frame_unwind_caller_pc (struct frame_info *frame); -/* Same as frame_unwind_caller_pc, but returns a boolean indication of - whether the caller PC is determinable (when the PC is unavailable, - it will not be), instead of possibly throwing an error trying to - read unavailable memory or registers. */ - -extern int frame_unwind_caller_pc_if_available (struct frame_info *this_frame, - CORE_ADDR *pc); - /* Discard the specified frame. Restoring the registers to the state of the caller. */ extern void frame_pop (struct frame_info *frame); diff --git a/gdb/stack.c b/gdb/stack.c index 9a12eb3..848bcb0a 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1408,6 +1408,7 @@ frame_info (char *addr_exp, int from_tty) CORE_ADDR frame_pc; int frame_pc_p; CORE_ADDR caller_pc; + volatile struct gdb_exception ex; fi = parse_frame_specification_1 (addr_exp, "No stack.", &selected_frame_p); gdbarch = get_frame_arch (fi); @@ -1493,11 +1494,29 @@ frame_info (char *addr_exp, int from_tty) sal.line); puts_filtered ("; "); wrap_here (" "); - printf_filtered ("saved %s ", pc_regname); - if (frame_unwind_caller_pc_if_available (fi, &caller_pc)) - fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout); + printf_filtered ("saved %s = ", pc_regname); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + caller_pc = frame_unwind_caller_pc (fi); + } + if (ex.reason < 0) + { + switch (ex.error) + { + case NOT_AVAILABLE_ERROR: + val_print_unavailable (gdb_stdout); + break; + case OPTIMIZED_OUT_ERROR: + val_print_not_saved (gdb_stdout); + break; + default: + fprintf_filtered (gdb_stdout, _("<error: %s>"), ex.message); + break; + } + } else - fputs_filtered ("<unavailable>", gdb_stdout); + fputs_filtered (paddress (gdbarch, caller_pc), gdb_stdout); printf_filtered ("\n"); if (calling_frame_info == NULL) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 14bf46c..52e7ddc 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-12-06 Pedro Alves <palves@redhat.com> + + * gdb.dwarf2/dw2-undefined-ret-addr.S: New file. + * gdb.dwarf2/dw2-undefined-ret-addr.c: New file. + * gdb.dwarf2/dw2-undefined-ret-addr.exp: New file. + 2013-12-06 Doug Evans <dje@google.com> * gdb.base/break.exp: Fix setting of $baz. diff --git a/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.S b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.S new file mode 100644 index 0000000..fc92016 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.S @@ -0,0 +1,508 @@ +/* + Copyright 2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + /* The FDE entry for "stop_frame" in the .debug_frame section has + been hand modified to mark the return address (rip) as undefined. + Otherwise this file is as generated by gcc 4.7.2 for x86_64. */ + .file "dw2-undefined-ret-addr.c" + .text +.Ltext0: + .globl stop_frame + .type stop_frame, @function +stop_frame: +.LFB0: + .file 1 "dw2-undefined-ret-addr.c" + .loc 1 19 0 + pushq %rbp +.LCFI0: + movq %rsp, %rbp +.LCFI1: + .loc 1 22 0 + popq %rbp +.LCFI2: + ret +.LFE0: + .size stop_frame, .-stop_frame + .globl first_frame + .type first_frame, @function +first_frame: +.LFB1: + .loc 1 26 0 + pushq %rbp +.LCFI3: + movq %rsp, %rbp +.LCFI4: + .loc 1 27 0 + movl $0, %eax + call stop_frame + .loc 1 28 0 + popq %rbp +.LCFI5: + ret +.LFE1: + .size first_frame, .-first_frame + .globl main + .type main, @function +main: +.LFB2: + .loc 1 32 0 + pushq %rbp +.LCFI6: + movq %rsp, %rbp +.LCFI7: + .loc 1 33 0 + movl $0, %eax + call first_frame + .loc 1 35 0 + movl $0, %eax + .loc 1 36 0 + popq %rbp +.LCFI8: + ret +.LFE2: + .size main, .-main + .section .debug_frame,"",@progbits +.Lframe0: + .long .LECIE0-.LSCIE0 +.LSCIE0: + .long 0xffffffff + .byte 0x1 + .string "" + .uleb128 0x1 + .sleb128 -8 + .byte 0x10 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 + .uleb128 0x1 + .align 8 +.LECIE0: + /* This FDE entry, for stop_frame was modified to mark + registers 0 -> 6 as being undefined. */ +.LSFDE0: + .long .LEFDE0-.LASFDE0 +.LASFDE0: + .long .Lframe0 + .quad .LFB0 + .quad .LFE0-.LFB0 + + /* START OF NEW CONTENT. */ + .byte 0x7 /* DW_CFA_undefined */ + .uleb128 0x10 /* ULEB128 register */ + /* END OF NEW CONTENT. */ + + .byte 0x4 + .long .LCFI0-.LFB0 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI1-.LCFI0 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI2-.LCFI1 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE0: +.LSFDE2: + .long .LEFDE2-.LASFDE2 +.LASFDE2: + .long .Lframe0 + .quad .LFB1 + .quad .LFE1-.LFB1 + .byte 0x4 + .long .LCFI3-.LFB1 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI4-.LCFI3 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI5-.LCFI4 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE2: +.LSFDE4: + .long .LEFDE4-.LASFDE4 +.LASFDE4: + .long .Lframe0 + .quad .LFB2 + .quad .LFE2-.LFB2 + .byte 0x4 + .long .LCFI6-.LFB2 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI7-.LCFI6 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI8-.LCFI7 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE4: + .section .eh_frame,"a",@progbits +.Lframe1: + .long .LECIE1-.LSCIE1 +.LSCIE1: + .long 0 + .byte 0x1 + .string "zR" + .uleb128 0x1 + .sleb128 -8 + .byte 0x10 + .uleb128 0x1 + .byte 0x3 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .byte 0x90 + .uleb128 0x1 + .align 8 +.LECIE1: +.LSFDE7: + .long .LEFDE7-.LASFDE7 +.LASFDE7: + .long .LASFDE7-.Lframe1 + .long .LFB0 + .long .LFE0-.LFB0 + .uleb128 0 + .byte 0x4 + .long .LCFI0-.LFB0 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI1-.LCFI0 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI2-.LCFI1 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE7: +.LSFDE9: + .long .LEFDE9-.LASFDE9 +.LASFDE9: + .long .LASFDE9-.Lframe1 + .long .LFB1 + .long .LFE1-.LFB1 + .uleb128 0 + .byte 0x4 + .long .LCFI3-.LFB1 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI4-.LCFI3 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI5-.LCFI4 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE9: +.LSFDE11: + .long .LEFDE11-.LASFDE11 +.LASFDE11: + .long .LASFDE11-.Lframe1 + .long .LFB2 + .long .LFE2-.LFB2 + .uleb128 0 + .byte 0x4 + .long .LCFI6-.LFB2 + .byte 0xe + .uleb128 0x10 + .byte 0x86 + .uleb128 0x2 + .byte 0x4 + .long .LCFI7-.LCFI6 + .byte 0xd + .uleb128 0x6 + .byte 0x4 + .long .LCFI8-.LCFI7 + .byte 0xc + .uleb128 0x7 + .uleb128 0x8 + .align 8 +.LEFDE11: + .text +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x8c + .value 0x2 + .long .Ldebug_abbrev0 + .byte 0x8 + .uleb128 0x1 + .long .LASF2 + .byte 0x1 + .long .LASF3 + .long .LASF4 + .quad .Ltext0 + .quad .Letext0 + .long .Ldebug_line0 + .uleb128 0x2 + .byte 0x1 + .long .LASF0 + .byte 0x1 + .byte 0x12 + .quad .LFB0 + .quad .LFE0 + .long .LLST0 + .byte 0x1 + .uleb128 0x3 + .byte 0x1 + .long .LASF1 + .byte 0x1 + .byte 0x19 + .quad .LFB1 + .quad .LFE1 + .long .LLST1 + .byte 0x1 + .uleb128 0x4 + .byte 0x1 + .long .LASF5 + .byte 0x1 + .byte 0x1f + .long 0x88 + .quad .LFB2 + .quad .LFE2 + .long .LLST2 + .byte 0x1 + .uleb128 0x5 + .byte 0x4 + .byte 0x5 + .string "int" + .byte 0 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x10 + .uleb128 0x6 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0xc + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x40 + .uleb128 0x6 + .uleb128 0x2117 + .uleb128 0xc + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0xc + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x40 + .uleb128 0x6 + .uleb128 0x2116 + .uleb128 0xc + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0xc + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x40 + .uleb128 0x6 + .uleb128 0x2116 + .uleb128 0xc + .byte 0 + .byte 0 + .uleb128 0x5 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .byte 0 + .section .debug_loc,"",@progbits +.Ldebug_loc0: +.LLST0: + .quad .LFB0-.Ltext0 + .quad .LCFI0-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad .LCFI0-.Ltext0 + .quad .LCFI1-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 16 + .quad .LCFI1-.Ltext0 + .quad .LCFI2-.Ltext0 + .value 0x2 + .byte 0x76 + .sleb128 16 + .quad .LCFI2-.Ltext0 + .quad .LFE0-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad 0 + .quad 0 +.LLST1: + .quad .LFB1-.Ltext0 + .quad .LCFI3-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad .LCFI3-.Ltext0 + .quad .LCFI4-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 16 + .quad .LCFI4-.Ltext0 + .quad .LCFI5-.Ltext0 + .value 0x2 + .byte 0x76 + .sleb128 16 + .quad .LCFI5-.Ltext0 + .quad .LFE1-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad 0 + .quad 0 +.LLST2: + .quad .LFB2-.Ltext0 + .quad .LCFI6-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad .LCFI6-.Ltext0 + .quad .LCFI7-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 16 + .quad .LCFI7-.Ltext0 + .quad .LCFI8-.Ltext0 + .value 0x2 + .byte 0x76 + .sleb128 16 + .quad .LCFI8-.Ltext0 + .quad .LFE2-.Ltext0 + .value 0x2 + .byte 0x77 + .sleb128 8 + .quad 0 + .quad 0 + .section .debug_aranges,"",@progbits + .long 0x2c + .value 0x2 + .long .Ldebug_info0 + .byte 0x8 + .byte 0 + .value 0 + .value 0 + .quad .Ltext0 + .quad .Letext0-.Ltext0 + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF0: + .string "stop_frame" +.LASF3: + .string "dw2-undefined-ret-addr.c" +.LASF2: + .string "GNU C 4.7.2" +.LASF1: + .string "first_frame" +.LASF5: + .string "main" +.LASF4: + .string "/home/username/src/gdb/testsuite/gdb.dwarf2" + .ident "GCC: (GNU) 4.7.2" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.c b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.c new file mode 100644 index 0000000..6c5b06a --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.c @@ -0,0 +1,36 @@ +/* + Copyright 2013 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +void +stop_frame () +{ + /* The debug information for this frame is modified in the accompanying + .S file, to mark the return address as undefined. */ +} + +void +first_frame () +{ + stop_frame (); +} + +int +main () +{ + first_frame (); + + return 0; +} diff --git a/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.exp b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.exp new file mode 100644 index 0000000..40ac356 --- /dev/null +++ b/gdb/testsuite/gdb.dwarf2/dw2-undefined-ret-addr.exp @@ -0,0 +1,58 @@ +# Copyright 2013 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +load_lib dwarf.exp + +standard_testfile .S + +# This test can only be run on targets which support DWARF-2 and use gas. +if ![dwarf2_support] { + return 0 +} + +# This test can only be run on x86-64 targets. +if {![istarget x86_64-*] || ![is_lp64_target]} { + return 0 +} + +if {[prepare_for_testing "$testfile.exp" "$testfile" $srcfile {nodebug}]} { + return -1 +} + +if ![runto "stop_frame"] { + return -1 +} + +# stop_frame should be the outermost frame. + +# Check that backtrace shows only frame #0. +gdb_test "bt" "#0\[ \]\+stop_frame \[^\r\n\]\+" + +# And that "up" doesn't work. +gdb_test "up" \ + "Initial frame selected; you cannot go up\\." \ + "up refuses to go up" + +# "info frame" unwinds the PC for "saved ... = ". Make sure that +# doesn't cause an error, and shows "<not saved>". +gdb_test "info frame" [join [list \ + "Stack level 0, frame at $hex\:" \ + " rip = $hex in stop_frame \\(dw2-undefined-ret-addr\\.c:22\\); saved rip = <not saved>" \ + " Outermost frame: outermost" \ + " source language c\\." \ + " Arglist at $hex, args\: " \ + " Locals at $hex, Previous frame's sp is $hex" \ + " Saved registers\:" \ + " rbp at $hex.*" \ +] "\r\n"] diff --git a/gdb/valprint.c b/gdb/valprint.c index 0124934..7ebcdfd 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -339,12 +339,18 @@ void val_print_optimized_out (const struct value *val, struct ui_file *stream) { if (val != NULL && value_lval_const (val) == lval_register) - fprintf_filtered (stream, _("<not saved>")); + val_print_not_saved (stream); else fprintf_filtered (stream, _("<optimized out>")); } void +val_print_not_saved (struct ui_file *stream) +{ + fprintf_filtered (stream, _("<not saved>")); +} + +void val_print_unavailable (struct ui_file *stream) { fprintf_filtered (stream, _("<unavailable>")); diff --git a/gdb/valprint.h b/gdb/valprint.h index 1d86ed7..8ed259d 100644 --- a/gdb/valprint.h +++ b/gdb/valprint.h @@ -163,6 +163,9 @@ extern int read_string (CORE_ADDR addr, int len, int width, extern void val_print_optimized_out (const struct value *val, struct ui_file *stream); +/* Prints "<not saved>" to STREAM. */ +extern void val_print_not_saved (struct ui_file *stream); + extern void val_print_unavailable (struct ui_file *stream); extern void val_print_invalid_address (struct ui_file *stream); |