diff options
-rw-r--r-- | gdb/ChangeLog | 6 | ||||
-rw-r--r-- | gdb/frame.c | 24 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/morestack.c | 105 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/morestack.exp | 52 |
5 files changed, 186 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 08b2b09..586d12e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2011-01-03 Jan Kratochvil <jan.kratochvil@redhat.com> + + * frame.c (get_prev_frame_1) <UNWIND_INNER_ID>: New variables + this_pc_in_block, morestack_msym and morestack_name. Check for + "__morestack" minimal symbol there. + 2011-01-03 Joel Brobecker <brobecker@adacore.com> * symfile.c (find_sym_fns): Add call to dont_repeat. diff --git a/gdb/frame.c b/gdb/frame.c index e36ba91..87122cd 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -1502,14 +1502,26 @@ get_prev_frame_1 (struct frame_info *this_frame) && frame_id_inner (get_frame_arch (this_frame->next), this_id, get_frame_id (this_frame->next))) { - if (frame_debug) + CORE_ADDR this_pc_in_block; + struct minimal_symbol *morestack_msym; + const char *morestack_name = NULL; + + /* gcc -fsplit-stack __morestack can continue the stack anywhere. */ + this_pc_in_block = get_frame_address_in_block (this_frame); + morestack_msym = lookup_minimal_symbol_by_pc (this_pc_in_block); + if (morestack_msym) + morestack_name = SYMBOL_LINKAGE_NAME (morestack_msym); + if (!morestack_name || strcmp (morestack_name, "__morestack") != 0) { - fprintf_unfiltered (gdb_stdlog, "-> "); - fprint_frame (gdb_stdlog, NULL); - fprintf_unfiltered (gdb_stdlog, " // this frame ID is inner }\n"); + if (frame_debug) + { + fprintf_unfiltered (gdb_stdlog, "-> "); + fprint_frame (gdb_stdlog, NULL); + fprintf_unfiltered (gdb_stdlog, " // this frame ID is inner }\n"); + } + this_frame->stop_reason = UNWIND_INNER_ID; + return NULL; } - this_frame->stop_reason = UNWIND_INNER_ID; - return NULL; } /* Check that this and the next frame are not identical. If they diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 24c3905..b934168 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-01-03 Jan Kratochvil <jan.kratochvil@redhat.com> + + * gdb.base/morestack.exp: New file. + * gdb.base/morestack.c: New file. + 2011-01-02 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.ada/gnat_ada.gpr: Fix copyright comment line regression by 2011. diff --git a/gdb/testsuite/gdb.base/morestack.c b/gdb/testsuite/gdb.base/morestack.c new file mode 100644 index 0000000..e612c73 --- /dev/null +++ b/gdb/testsuite/gdb.base/morestack.c @@ -0,0 +1,105 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2011 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/>. */ + +/* Based on the gcc testcase `gcc/testsuite/gcc.dg/split-1.c'. This test + needs to use setrlimit to set the stack size, so it can only run on Unix. + */ + +#include <stdlib.h> +#include <sys/types.h> +#include <sys/resource.h> +#include <stdio.h> +#include <sys/mman.h> + +/* Use a noinline function to ensure that the buffer is not removed + from the stack. */ +static void use_buffer (char *buf) __attribute__ ((noinline)); +static void +use_buffer (char *buf) +{ + buf[0] = '\0'; +} + +static volatile int marker_var; + +static void +marker_miss (void) +{ + marker_var = 0; +} + +static void +marker_hit (void) +{ + marker_var = 0; +} + +void *reserved; +#define RESERVED_SIZE 0x1000000 + +/* Each recursive call uses 10,000 bytes. We call it 1000 times, + using a total of 10,000,000 bytes. If -fsplit-stack is not + working, that will overflow our stack limit. */ + +static void +down (int i) +{ + char buf[10000]; + static void *last; + + if (last && last < (void *) buf) + { + printf ("%d: %p < %p\n", i, last, buf); + marker_hit (); + } + last = buf; + + if (i == 500) + { + if (munmap (reserved, RESERVED_SIZE) != 0) + abort (); + reserved = NULL; + } + + if (i > 0) + { + use_buffer (buf); + down (i - 1); + } + else + marker_miss (); +} + +int +main (void) +{ + struct rlimit r; + + reserved = mmap (NULL, RESERVED_SIZE, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (reserved == MAP_FAILED) + abort (); + + /* We set a stack limit because we are usually invoked via make, and + make sets the stack limit to be as large as possible. */ + r.rlim_cur = 8192 * 1024; + r.rlim_max = 8192 * 1024; + if (setrlimit (RLIMIT_STACK, &r) != 0) + abort (); + down (1000); + return 0; +} diff --git a/gdb/testsuite/gdb.base/morestack.exp b/gdb/testsuite/gdb.base/morestack.exp new file mode 100644 index 0000000..c7ea05b9 --- /dev/null +++ b/gdb/testsuite/gdb.base/morestack.exp @@ -0,0 +1,52 @@ +# Copyright (C) 2011 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/>. + +if [get_compiler_info "ignored"] { + return -1 +} + +if {$gcc_compiled == 0} { + return -1 +} + +set testfile morestack +if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {additional_flags=-fsplit-stack}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_breakpoint "marker_hit" +gdb_breakpoint "marker_miss" + +set test "continue" +gdb_test_multiple $test $test { + -re "marker_hit.*$gdb_prompt $" { + pass $test + } + -re "marker_miss.*$gdb_prompt $" { + # The testcase failed to violated the frame_id_inner condition by + # handing inner frame with higher (on the stack-grows-down arches) + # $sp address than the outer frame. + xfail $test + return 0 + } +} + +# FAIL was on `bt' producing: +# Backtrace stopped: previous frame inner to this frame (corrupt stack?) +gdb_test "up 3000" " in main .*" |